os/kernelhwsrv/kernel/eka/drivers/ecomm/d_comm.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\ecomm\d_comm.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include <drivers/comm.h>
sl@0
    19
#include <kernel/kern_priv.h>
sl@0
    20
#include <e32hal.h>
sl@0
    21
#include <e32uid.h>
sl@0
    22
sl@0
    23
// Logging
sl@0
    24
#define LOG_ON(x) Kern::Printf##x
sl@0
    25
#define LOG_OFF(x)
sl@0
    26
#define LOG		LOG_OFF
sl@0
    27
sl@0
    28
sl@0
    29
//#define __UART_RX_ERROR(x)    *(TUint*)0xfeedface=(x)
sl@0
    30
//#define __OVERRUN() *(TUint*)0xfaece5=0
sl@0
    31
sl@0
    32
#define __UART_RX_ERROR(x)
sl@0
    33
#define __OVERRUN()
sl@0
    34
sl@0
    35
_LIT(KLddName,"Comm");
sl@0
    36
sl@0
    37
sl@0
    38
const TUint KXoffSignal=0x80;
sl@0
    39
//
sl@0
    40
const TUint KBreaking=0x02;
sl@0
    41
const TUint KBreakPending=0x04;
sl@0
    42
//
sl@0
    43
enum TPanic
sl@0
    44
	{
sl@0
    45
	ESetConfigWhileRequestPending,
sl@0
    46
	ESetSignalsSetAndClear,
sl@0
    47
	EResetBuffers,
sl@0
    48
	ESetReceiveBufferLength,
sl@0
    49
	};
sl@0
    50
sl@0
    51
DECLARE_STANDARD_LDD()
sl@0
    52
	{
sl@0
    53
	return new DDeviceComm;
sl@0
    54
	}
sl@0
    55
sl@0
    56
DDeviceComm::DDeviceComm()
sl@0
    57
//
sl@0
    58
// Constructor
sl@0
    59
//
sl@0
    60
	{
sl@0
    61
	LOG(("DDeviceComm::DDeviceComm"));
sl@0
    62
	iParseMask=KDeviceAllowAll;
sl@0
    63
	iUnitsMask=0xffffffff; // Leave units decision to the PDD
sl@0
    64
	iVersion=TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
sl@0
    65
	}
sl@0
    66
sl@0
    67
TInt DDeviceComm::Install()
sl@0
    68
//
sl@0
    69
// Install the device driver.
sl@0
    70
//
sl@0
    71
	{
sl@0
    72
	LOG(("DDeviceComm::Install"));
sl@0
    73
	return(SetName(&KLddName));
sl@0
    74
	}
sl@0
    75
sl@0
    76
void DDeviceComm::GetCaps(TDes8& aDes) const
sl@0
    77
//
sl@0
    78
// Return the Comm capabilities.
sl@0
    79
//
sl@0
    80
	{
sl@0
    81
	LOG(("DDeviceComm::GetCaps"));
sl@0
    82
	TPckgBuf<TCapsDevCommV01> b;
sl@0
    83
	b().version=TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
sl@0
    84
	Kern::InfoCopy(aDes,b);
sl@0
    85
	}
sl@0
    86
sl@0
    87
TInt DDeviceComm::Create(DLogicalChannelBase*& aChannel)
sl@0
    88
//
sl@0
    89
// Create a channel on the device.
sl@0
    90
//
sl@0
    91
	{
sl@0
    92
	LOG(("DDeviceComm::Create"));
sl@0
    93
	aChannel=new DChannelComm;
sl@0
    94
	return aChannel?KErrNone:KErrNoMemory;
sl@0
    95
	}
sl@0
    96
sl@0
    97
DChannelComm::DChannelComm()
sl@0
    98
//
sl@0
    99
// Constructor
sl@0
   100
//
sl@0
   101
	:	iPowerUpDfc(DChannelComm::PowerUpDfc,this,3),
sl@0
   102
		iPowerDownDfc(DChannelComm::PowerDownDfc,this,3),
sl@0
   103
		iRxDrainDfc(DChannelComm::DrainRxDfc,this,2),
sl@0
   104
		iRxCompleteDfc(DChannelComm::CompleteRxDfc,this,2),
sl@0
   105
		iTxFillDfc(DChannelComm::FillTxDfc,this,2),
sl@0
   106
		iTxCompleteDfc(DChannelComm::CompleteTxDfc,this,2),
sl@0
   107
		iTimerDfc(DChannelComm::TimerDfcFn,this,3),
sl@0
   108
		iSigNotifyDfc(DChannelComm::SigNotifyDfc,this,2),
sl@0
   109
//		iTurnaroundMinMilliSeconds(0),
sl@0
   110
//		iTurnaroundTimerRunning(EFalse),
sl@0
   111
//		iTurnaroundTransmitDelayed(EFalse),
sl@0
   112
		iTurnaroundTimer(DChannelComm::TurnaroundStartDfc, this),
sl@0
   113
		iTurnaroundDfc(DChannelComm::TurnaroundTimeout, this, 2),
sl@0
   114
		iTimer(DChannelComm::MsCallBack,this),
sl@0
   115
		iBreakDfc(DChannelComm::FinishBreakDfc, this, 2),
sl@0
   116
		iLock(TSpinLock::EOrderGenericIrqLow3)
sl@0
   117
	{
sl@0
   118
	LOG(("DChannelComm"));
sl@0
   119
//
sl@0
   120
// Setup the default config
sl@0
   121
//
sl@0
   122
	iConfig.iRate=EBps9600;
sl@0
   123
	iConfig.iDataBits=EData8;
sl@0
   124
	iConfig.iStopBits=EStop1;
sl@0
   125
	iConfig.iParity=EParityNone;
sl@0
   126
	iConfig.iFifo=EFifoEnable;
sl@0
   127
	iConfig.iHandshake=KConfigObeyCTS;
sl@0
   128
	iConfig.iParityError=KConfigParityErrorFail;
sl@0
   129
	iConfig.iSIREnable=ESIRDisable;
sl@0
   130
//	iConfig.iTerminatorCount=0;
sl@0
   131
//	iConfig.iTerminator[0]=0;
sl@0
   132
//	iConfig.iTerminator[1]=0;
sl@0
   133
//	iConfig.iTerminator[2]=0;
sl@0
   134
//	iConfig.iTerminator[3]=0;
sl@0
   135
	iConfig.iXonChar=0x11; // XON
sl@0
   136
	iConfig.iXoffChar=0x13; // XOFF
sl@0
   137
//	iConfig.iSpecialRate=0;
sl@0
   138
//	iConfig.iParityErrorChar=0;
sl@0
   139
	iRxXonChar=0xffffffff;
sl@0
   140
	iRxXoffChar=0xffffffff;
sl@0
   141
	iStatus=EOpen;
sl@0
   142
//	iFlags=0;
sl@0
   143
//	iSignals=0;
sl@0
   144
//	iFailSignals=0;
sl@0
   145
//	iHoldSignals=0;
sl@0
   146
//	iFlowControlSignals=0;
sl@0
   147
//	iAutoSignals=0;
sl@0
   148
//	iTerminatorMask[0...31]=0;
sl@0
   149
//	iShutdown=EFalse;
sl@0
   150
//	iRxCharBuf=NULL;
sl@0
   151
//	iRxErrorBuf=NULL;
sl@0
   152
//	iRxPutIndex=0;
sl@0
   153
//	iRxGetIndex=0;
sl@0
   154
//	iRxBufSize=0;
sl@0
   155
//	iFlowControlLowerThreshold=0;
sl@0
   156
//	iFlowControlUpperThreshold=0;
sl@0
   157
//	iRxDrainThreshold=0;
sl@0
   158
//	iRxBufCompleteIndex=0;
sl@0
   159
//	iInputHeld=EFalse;
sl@0
   160
//	iRxClientBufReq=NULL;
sl@0
   161
//	iRxDesPos=0;
sl@0
   162
//	iRxLength=0;
sl@0
   163
//	iRxOutstanding=EFalse;
sl@0
   164
//	iRxError=KErrNone;
sl@0
   165
//	iTxBuffer=NULL;
sl@0
   166
//	iTxPutIndex=0;
sl@0
   167
//	iTxGetIndex=0;
sl@0
   168
//	iTxBufSize=0;
sl@0
   169
//	iTxFillThreshold=0;
sl@0
   170
	iOutputHeld=0;
sl@0
   171
	iJamChar=KTxNoChar;
sl@0
   172
//	iTxDesPtr=NULL;
sl@0
   173
//	iTxDesPos=0;
sl@0
   174
//	iTxDesLength=0;
sl@0
   175
//	iTxOutstanding=EFalse;
sl@0
   176
//	iTxError=KErrNone;
sl@0
   177
sl@0
   178
//	iTimeout=10;
sl@0
   179
	iTimeout=NKern::TimerTicks(5);
sl@0
   180
	iClient=&Kern::CurrentThread();
sl@0
   181
	iClient->Open();
sl@0
   182
//	iSigNotifyMask=0;
sl@0
   183
//	iSignalsPtr=NULL;
sl@0
   184
//	iSigNotifyStatus=NULL;
sl@0
   185
	iBreakStatus=NULL;
sl@0
   186
	iNotifiedSignals=0xffffffff;
sl@0
   187
	iPinObjSetConfig=NULL;
sl@0
   188
	}
sl@0
   189
sl@0
   190
DChannelComm::~DChannelComm()
sl@0
   191
//
sl@0
   192
// Destructor
sl@0
   193
//
sl@0
   194
	{
sl@0
   195
	LOG(("~DChannelComm"));
sl@0
   196
	if (iPowerHandler)
sl@0
   197
		{
sl@0
   198
		iPowerHandler->Remove(); 
sl@0
   199
		delete iPowerHandler;
sl@0
   200
		}
sl@0
   201
    if (iRxCharBuf)
sl@0
   202
        Kern::Free(iRxCharBuf);
sl@0
   203
    if (iTxBuffer)
sl@0
   204
        Kern::Free(iTxBuffer);
sl@0
   205
	if (iBreakStatus)
sl@0
   206
		Kern::DestroyClientRequest(iBreakStatus);
sl@0
   207
	if (iSignalsReq)
sl@0
   208
		Kern::DestroyClientRequest(iSignalsReq);
sl@0
   209
	if (iPinObjSetConfig)
sl@0
   210
		Kern::DestroyVirtualPinObject(iPinObjSetConfig);
sl@0
   211
	Kern::SafeClose((DObject*&)iClient, NULL);
sl@0
   212
	}
sl@0
   213
sl@0
   214
sl@0
   215
void DChannelComm::Complete(TInt aMask, TInt aReason)
sl@0
   216
	{
sl@0
   217
	LOG(("Complete(aMask=%x aReason=%d)", aMask, aReason));
sl@0
   218
	if (aMask & ERx)
sl@0
   219
		iRxBufReq.Complete(iClient, aReason);
sl@0
   220
	if (aMask & ETx)
sl@0
   221
		iTxBufReq.Complete(iClient, aReason);
sl@0
   222
	if (aMask & ESigChg)
sl@0
   223
		Kern::QueueRequestComplete(iClient, iSignalsReq, aReason);
sl@0
   224
	if ((aMask & EBreak) && iBreakStatus && iBreakStatus->IsReady())
sl@0
   225
		Kern::QueueRequestComplete(iClient, iBreakStatus, aReason);
sl@0
   226
	}
sl@0
   227
sl@0
   228
TInt DChannelComm::Shutdown()
sl@0
   229
	{
sl@0
   230
	__KTRACE_OPT(KPOWER,Kern::Printf("DChannelComm::Shutdown()"));
sl@0
   231
	LOG(("Shutdown()"));
sl@0
   232
sl@0
   233
    if (iStatus == EActive)
sl@0
   234
        Stop(EStopPwrDown);
sl@0
   235
sl@0
   236
    Complete(EAll, KErrAbort);
sl@0
   237
sl@0
   238
	// UART interrupts are disabled; must make sure DFCs are not queued.
sl@0
   239
	iRxDrainDfc.Cancel();
sl@0
   240
	iRxCompleteDfc.Cancel();
sl@0
   241
	iTxFillDfc.Cancel();
sl@0
   242
	iTxCompleteDfc.Cancel();
sl@0
   243
	iTimer.Cancel();
sl@0
   244
	iTurnaroundTimer.Cancel();
sl@0
   245
	iTurnaroundDfc.Cancel();
sl@0
   246
	iTimerDfc.Cancel();
sl@0
   247
	iSigNotifyDfc.Cancel();
sl@0
   248
	iPowerUpDfc.Cancel();
sl@0
   249
	iPowerDownDfc.Cancel();
sl@0
   250
	iBreakTimer.Cancel();
sl@0
   251
	iBreakDfc.Cancel();
sl@0
   252
	
sl@0
   253
	if (iPdd)
sl@0
   254
		SetSignals(0,iFlowControlSignals|iAutoSignals);
sl@0
   255
sl@0
   256
	return KErrCompletion;
sl@0
   257
	}
sl@0
   258
sl@0
   259
TInt DChannelComm::DoCreate(TInt aUnit, const TDesC8* /*anInfo*/, const TVersion &aVer)
sl@0
   260
//
sl@0
   261
// Create the channel from the passed info.
sl@0
   262
//
sl@0
   263
	{
sl@0
   264
	LOG(("DoCreate(aUnit=%d,...)", aUnit));
sl@0
   265
	if(!Kern::CurrentThreadHasCapability(ECapabilityCommDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by ECOMM.LDD (Comm Driver)")))
sl@0
   266
		return KErrPermissionDenied;
sl@0
   267
	if (!Kern::QueryVersionSupported(TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber),aVer))
sl@0
   268
		return KErrNotSupported;
sl@0
   269
sl@0
   270
	// set up the correct DFC queue
sl@0
   271
	SetDfcQ(((DComm*)iPdd)->DfcQ(aUnit));
sl@0
   272
	iPowerUpDfc.SetDfcQ(iDfcQ);
sl@0
   273
	iPowerDownDfc.SetDfcQ(iDfcQ);
sl@0
   274
	iRxDrainDfc.SetDfcQ(iDfcQ);
sl@0
   275
	iRxCompleteDfc.SetDfcQ(iDfcQ);
sl@0
   276
	iTxFillDfc.SetDfcQ(iDfcQ);
sl@0
   277
	iTxCompleteDfc.SetDfcQ(iDfcQ);
sl@0
   278
	iTimerDfc.SetDfcQ(iDfcQ);
sl@0
   279
	iSigNotifyDfc.SetDfcQ(iDfcQ);
sl@0
   280
	iTurnaroundDfc.SetDfcQ(iDfcQ);
sl@0
   281
	iBreakDfc.SetDfcQ(iDfcQ);
sl@0
   282
	iMsgQ.Receive();
sl@0
   283
sl@0
   284
	// initialise the TX buffer
sl@0
   285
	iTxBufSize=KTxBufferSize;
sl@0
   286
	iTxBuffer=(TUint8*)Kern::Alloc(iTxBufSize);
sl@0
   287
	if (!iTxBuffer)
sl@0
   288
		return KErrNoMemory;
sl@0
   289
	iTxFillThreshold=iTxBufSize>>1;
sl@0
   290
sl@0
   291
	// initialise the RX buffer
sl@0
   292
	iRxBufSize=KDefaultRxBufferSize;
sl@0
   293
	iRxCharBuf=(TUint8*)Kern::Alloc(iRxBufSize<<1);
sl@0
   294
	if (!iRxCharBuf)
sl@0
   295
		return KErrNoMemory;
sl@0
   296
	iRxErrorBuf=iRxCharBuf+iRxBufSize;
sl@0
   297
	iFlowControlLowerThreshold=iRxBufSize>>2;
sl@0
   298
	iFlowControlUpperThreshold=3*iRxBufSize>>2;
sl@0
   299
	iRxDrainThreshold=iRxBufSize>>1;
sl@0
   300
sl@0
   301
	// Create request objects
sl@0
   302
	TInt r = Kern::CreateClientDataRequest(iSignalsReq);
sl@0
   303
	if (r==KErrNone)
sl@0
   304
		r = Kern::CreateClientRequest(iBreakStatus);
sl@0
   305
	if (r==KErrNone)
sl@0
   306
		r = iRxBufReq.Create();
sl@0
   307
	if (r==KErrNone)
sl@0
   308
		r = iTxBufReq.Create();
sl@0
   309
	if (r==KErrNone)
sl@0
   310
		r = Kern::CreateVirtualPinObject(iPinObjSetConfig);
sl@0
   311
	if (r != KErrNone)
sl@0
   312
		return r;
sl@0
   313
sl@0
   314
	((DComm *)iPdd)->iLdd=this;
sl@0
   315
	PddCheckConfig(iConfig);
sl@0
   316
	iFailSignals=FailSignals(iConfig.iHandshake);
sl@0
   317
	iHoldSignals=HoldSignals(iConfig.iHandshake);
sl@0
   318
	iFlowControlSignals=FlowControlSignals(iConfig.iHandshake);
sl@0
   319
	iAutoSignals=AutoSignals(iConfig.iHandshake);
sl@0
   320
sl@0
   321
	// create the power handler
sl@0
   322
	iPowerHandler=new DCommPowerHandler(this);
sl@0
   323
	if (!iPowerHandler)
sl@0
   324
		return KErrNoMemory;
sl@0
   325
	iPowerHandler->Add();
sl@0
   326
	DoPowerUp();
sl@0
   327
sl@0
   328
	return KErrNone;
sl@0
   329
	}
sl@0
   330
sl@0
   331
TInt DChannelComm::RequestUserHandle(DThread* aThread, TOwnerType aType)
sl@0
   332
	{
sl@0
   333
	// Ensure that each channel can only be used by a single thread.
sl@0
   334
	return (aThread!=iClient) ?  KErrAccessDenied : KErrNone;
sl@0
   335
	}
sl@0
   336
sl@0
   337
void DChannelComm::MsCallBack(TAny* aPtr)
sl@0
   338
	{
sl@0
   339
	// called from ISR when timer completes
sl@0
   340
	DChannelComm *pC=(DChannelComm*)aPtr;
sl@0
   341
	pC->iTimerDfc.Add();
sl@0
   342
	}
sl@0
   343
sl@0
   344
void DChannelComm::TimerDfcFn(TAny* aPtr)
sl@0
   345
	{
sl@0
   346
	DChannelComm *pC=(DChannelComm*)aPtr;
sl@0
   347
	pC->TimerDfc();
sl@0
   348
	}
sl@0
   349
sl@0
   350
void DChannelComm::TimerDfc()
sl@0
   351
	{
sl@0
   352
	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
   353
	if (iRxOutstanding)
sl@0
   354
		{
sl@0
   355
		if (iRxGetIndex==iRxPutIndex)
sl@0
   356
			{
sl@0
   357
			// buffer empty after timeout period, so complete
sl@0
   358
			iRxBufCompleteIndex=iRxPutIndex;
sl@0
   359
			iRxOutstanding=EFalse;
sl@0
   360
			iRxOneOrMore=0;
sl@0
   361
			__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   362
			DoCompleteRx();
sl@0
   363
			return;
sl@0
   364
			}
sl@0
   365
		// buffer not empty, so drain buffer and requeue timer
sl@0
   366
		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   367
		DoDrainRxBuffer(iRxPutIndex);
sl@0
   368
		return;
sl@0
   369
		}
sl@0
   370
	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   371
	}
sl@0
   372
sl@0
   373
void DChannelComm::DrainRxDfc(TAny* aPtr)
sl@0
   374
	{
sl@0
   375
	DChannelComm *pC=(DChannelComm*)aPtr;
sl@0
   376
	pC->DoDrainRxBuffer(pC->iRxPutIndex);
sl@0
   377
	}
sl@0
   378
sl@0
   379
// Drain RX buffer in a DFC
sl@0
   380
void DChannelComm::DoDrainRxBuffer(TInt aEndIndex)
sl@0
   381
	{
sl@0
   382
	// if RX completion DFC is queued, leave buffer draining to it
sl@0
   383
	if (iRxCompleteDfc.Queued())
sl@0
   384
		return;
sl@0
   385
sl@0
   386
	LOG(("DoDrainRxBuffer(aEndIndex=%d) iRxDesPos=%d iRxBufReq.iLen=%d", aEndIndex, iRxDesPos, iRxBufReq.iLen));
sl@0
   387
    
sl@0
   388
	// If there's an Rx request with bytes outstanding...
sl@0
   389
	if (iRxBufReq.iBuf && iRxDesPos<iRxBufReq.iLen)
sl@0
   390
        {
sl@0
   391
        TInt space=iRxBufReq.iLen-iRxDesPos; // the amount of the client buffer left to fill
sl@0
   392
        TInt avail=aEndIndex-iRxGetIndex;	 // the amount of data in the Rx buffer to copy to the client buffer
sl@0
   393
        if (avail<0) // true if the data to drain wraps around the end of the buffer (i.e. the last byte to copy has a linear address less than that of the first byte)
sl@0
   394
            avail+=iRxBufSize;
sl@0
   395
        TInt len=Min(space,avail); // total number of bytes to drain
sl@0
   396
sl@0
   397
		// Drain up to (but not beyond) the end of the Rx buffer
sl@0
   398
        TInt len1=Min(len,iRxBufSize-iRxGetIndex);  // number of bytes to the end of the buffer
sl@0
   399
        TPtrC8 des(iRxCharBuf+iRxGetIndex,len1);
sl@0
   400
sl@0
   401
		TInt r = Kern::ThreadBufWrite(iClient, iRxBufReq.iBuf, des, iRxDesPos, KChunkShiftBy0, iClient);
sl@0
   402
        if (r != KErrNone)
sl@0
   403
            {
sl@0
   404
            iRxError=r;
sl@0
   405
            DoCompleteRx();
sl@0
   406
            return;
sl@0
   407
            }
sl@0
   408
sl@0
   409
		// Update the client buffer offset and the Rx buffer read pointer with what we've done so far
sl@0
   410
        TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
   411
        iRxDesPos += len1;
sl@0
   412
        iRxGetIndex+=len1;
sl@0
   413
        if (iRxGetIndex>=iRxBufSize)
sl@0
   414
            iRxGetIndex-=iRxBufSize;
sl@0
   415
        __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   416
sl@0
   417
		// If the data wraps around the end of the Rx buffer, now write out the second part
sl@0
   418
		// which starts at the beginning of the Rx buffer.
sl@0
   419
        len-=len1;
sl@0
   420
        if (len)
sl@0
   421
            {
sl@0
   422
            des.Set(iRxCharBuf,len);
sl@0
   423
			r=Kern::ThreadBufWrite(iClient, iRxBufReq.iBuf, des, iRxDesPos, KChunkShiftBy0, iClient);
sl@0
   424
            if (r != KErrNone)
sl@0
   425
                {
sl@0
   426
                iRxError=r;
sl@0
   427
                DoCompleteRx();
sl@0
   428
                return;
sl@0
   429
                }
sl@0
   430
sl@0
   431
			// Update client buffer offset and Rx buffer read offset
sl@0
   432
            irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
   433
            iRxDesPos += len;
sl@0
   434
            iRxGetIndex+=len;
sl@0
   435
            __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   436
            }
sl@0
   437
sl@0
   438
        // release flow control if necessary
sl@0
   439
        if (iInputHeld && RxCount()<=iFlowControlLowerThreshold)
sl@0
   440
            ReleaseFlowControl();
sl@0
   441
sl@0
   442
        // if we are doing ReadOneOrMore, start the timer
sl@0
   443
        if (iRxOneOrMore>0)
sl@0
   444
            {
sl@0
   445
            iTimer.OneShot(iTimeout);
sl@0
   446
            }
sl@0
   447
        }
sl@0
   448
    }
sl@0
   449
sl@0
   450
sl@0
   451
void DChannelComm::RxComplete()
sl@0
   452
{
sl@0
   453
	if (NKern::CurrentContext()==NKern::EInterrupt)
sl@0
   454
		iRxCompleteDfc.Add();
sl@0
   455
	else
sl@0
   456
		DoCompleteRx();			
sl@0
   457
}
sl@0
   458
sl@0
   459
sl@0
   460
void DChannelComm::CompleteRxDfc(TAny* aPtr)
sl@0
   461
	{
sl@0
   462
	DChannelComm *pC=(DChannelComm*)aPtr;
sl@0
   463
	pC->DoCompleteRx();
sl@0
   464
	}
sl@0
   465
sl@0
   466
void DChannelComm::DoCompleteRx()
sl@0
   467
	{
sl@0
   468
    LOG(("DoCompleteRx()"));
sl@0
   469
	if (iRxOneOrMore>0)
sl@0
   470
		iTimer.Cancel();
sl@0
   471
	if (iRxBufReq.iLen)
sl@0
   472
        {
sl@0
   473
        iRxOneOrMore=0;
sl@0
   474
        DoDrainRxBuffer(iRxBufCompleteIndex);
sl@0
   475
		iRxBufReq.Complete(iClient, iRxError);
sl@0
   476
		iRxDesPos=0;
sl@0
   477
sl@0
   478
        iRxError=KErrNone;
sl@0
   479
        // start Turnaround timer (got here because it received all data, timed out on a ReadOneOrMore or was terminated
sl@0
   480
        // early by FailSignals)
sl@0
   481
        RestartTurnaroundTimer();
sl@0
   482
        }
sl@0
   483
    else
sl@0
   484
        {
sl@0
   485
        Complete(ERx,KErrNone);
sl@0
   486
        // do not start Turnaround (got here on a request Data Available Notification)
sl@0
   487
        }
sl@0
   488
    }
sl@0
   489
sl@0
   490
sl@0
   491
void DChannelComm::TxComplete()
sl@0
   492
{
sl@0
   493
	if (NKern::CurrentContext()==NKern::EInterrupt)
sl@0
   494
		iTxCompleteDfc.Add(); 
sl@0
   495
	else
sl@0
   496
		DoCompleteTx();			
sl@0
   497
}
sl@0
   498
sl@0
   499
sl@0
   500
void DChannelComm::FillTxDfc(TAny* aPtr)
sl@0
   501
	{
sl@0
   502
	DChannelComm *pC=(DChannelComm*)aPtr;
sl@0
   503
	pC->DoFillTxBuffer();
sl@0
   504
	}
sl@0
   505
sl@0
   506
// Fill TX buffer in a DFC
sl@0
   507
void DChannelComm::DoFillTxBuffer()
sl@0
   508
	{
sl@0
   509
    LOG(("DFTB %d =%d",iTxDesPos,iTxBufReq.iLen));
sl@0
   510
	if (iTxBufReq.iBuf && iTxDesPos<iTxBufReq.iLen)
sl@0
   511
        {
sl@0
   512
        TInt space=iTxBufSize-TxCount()-1;
sl@0
   513
        TInt remaining=iTxBufReq.iLen-iTxDesPos;
sl@0
   514
        TInt len=Min(space,remaining);              // number of chars to transfer
sl@0
   515
        TInt len1=Min(len,iTxBufSize-iTxPutIndex);  // number of chars to wrap point
sl@0
   516
        TPtr8 des(iTxBuffer+iTxPutIndex,len1,len1);
sl@0
   517
        LOG(("DFTxB sp = %d rem = %d iOPH = %d",space, remaining,iOutputHeld));
sl@0
   518
		TInt r=Kern::ThreadBufRead(iClient, iTxBufReq.iBuf, des, iTxDesPos, KChunkShiftBy0);
sl@0
   519
        if (r != KErrNone)
sl@0
   520
            {
sl@0
   521
            iTxError=r;
sl@0
   522
            DoCompleteTx();
sl@0
   523
            return;
sl@0
   524
            }
sl@0
   525
sl@0
   526
        TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
   527
        iTxDesPos+=len1;
sl@0
   528
        iTxPutIndex+=len1;
sl@0
   529
        if (iTxPutIndex>=iTxBufSize)
sl@0
   530
            iTxPutIndex-=iTxBufSize;
sl@0
   531
        __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   532
sl@0
   533
        len-=len1;
sl@0
   534
        if (len)
sl@0
   535
            {
sl@0
   536
            des.Set(iTxBuffer,len,len);
sl@0
   537
			r=Kern::ThreadBufRead(iClient, iTxBufReq.iBuf, des, iTxDesPos, KChunkShiftBy0);
sl@0
   538
            if (r != KErrNone)
sl@0
   539
                {
sl@0
   540
                iTxError=r;
sl@0
   541
                DoCompleteTx();
sl@0
   542
                return;
sl@0
   543
                }
sl@0
   544
sl@0
   545
            irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
   546
            iTxDesPos+=len;
sl@0
   547
            iTxPutIndex+=len;
sl@0
   548
            __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   549
            }
sl@0
   550
        if (iTxDesPos==iTxBufReq.iLen)
sl@0
   551
            {
sl@0
   552
            // we have used up the client descriptor
sl@0
   553
            if (iConfig.iHandshake & KConfigWriteBufferedComplete)
sl@0
   554
                {
sl@0
   555
                iTxOutstanding=EFalse;
sl@0
   556
                DoCompleteTx();
sl@0
   557
                }
sl@0
   558
            }
sl@0
   559
        // if TX buffer not empty and not flow controlled, make sure TX is enabled
sl@0
   560
        if (iTxPutIndex!=iTxGetIndex  && (!iOutputHeld))
sl@0
   561
            {
sl@0
   562
            LOG(("Calling - DoTxBuff->ETx"));
sl@0
   563
            EnableTransmit();
sl@0
   564
            }
sl@0
   565
        }
sl@0
   566
    }
sl@0
   567
sl@0
   568
void DChannelComm::CompleteTxDfc(TAny* aPtr)
sl@0
   569
	{
sl@0
   570
	DChannelComm *pC=(DChannelComm*)aPtr;
sl@0
   571
	pC->DoCompleteTx();
sl@0
   572
	}
sl@0
   573
sl@0
   574
void DChannelComm::DoCompleteTx()
sl@0
   575
	{
sl@0
   576
	Complete(ETx,iTxError);
sl@0
   577
	iTxError=KErrNone;
sl@0
   578
	}
sl@0
   579
sl@0
   580
void DChannelComm::Start()
sl@0
   581
//
sl@0
   582
// Start the driver receiving.
sl@0
   583
//
sl@0
   584
	{
sl@0
   585
	LOG(("Start()"));
sl@0
   586
	if (iStatus!=EClosed)
sl@0
   587
		{
sl@0
   588
		PddConfigure(iConfig);
sl@0
   589
		PddStart();
sl@0
   590
		iStatus=EActive;
sl@0
   591
		if ((iConfig.iHandshake & KConfigSendXoff) && iJamChar>=0)
sl@0
   592
			EnableTransmit(); // Send XOn if there is one
sl@0
   593
		}
sl@0
   594
	}
sl@0
   595
sl@0
   596
void DChannelComm::BreakOn()
sl@0
   597
//
sl@0
   598
// Start the driver breaking.
sl@0
   599
//
sl@0
   600
	{
sl@0
   601
	LOG(("BreakOn()"));
sl@0
   602
	iFlags&=(~KBreakPending);
sl@0
   603
	iFlags|=KBreaking;
sl@0
   604
	PddBreak(ETrue);
sl@0
   605
	iBreakTimer.OneShot(iBreakTimeMicroSeconds, DChannelComm::FinishBreak, this);
sl@0
   606
	}
sl@0
   607
sl@0
   608
void DChannelComm::BreakOff()
sl@0
   609
//
sl@0
   610
// Stop the driver breaking.
sl@0
   611
//
sl@0
   612
	{
sl@0
   613
	LOG(("BreakOff()"));
sl@0
   614
	PddBreak(EFalse);
sl@0
   615
	iFlags&=(~(KBreakPending|KBreaking));
sl@0
   616
	}
sl@0
   617
sl@0
   618
void DChannelComm::AssertFlowControl()
sl@0
   619
	{
sl@0
   620
	iInputHeld=ETrue;
sl@0
   621
	SetSignals(0,iFlowControlSignals);
sl@0
   622
	if (iConfig.iHandshake&KConfigSendXoff)		// Doing input XON/XOFF
sl@0
   623
		{
sl@0
   624
		iJamChar=iConfig.iXoffChar;				// set up to send Xoff
sl@0
   625
		EnableTransmit();						// Make sure we are transmitting
sl@0
   626
		}
sl@0
   627
	}
sl@0
   628
sl@0
   629
void DChannelComm::ReleaseFlowControl()
sl@0
   630
	{
sl@0
   631
	iInputHeld=EFalse;
sl@0
   632
	SetSignals(iFlowControlSignals,0);
sl@0
   633
	if (iConfig.iHandshake&KConfigSendXoff)		// Doing input XON/XOFF
sl@0
   634
		{
sl@0
   635
		iJamChar=iConfig.iXonChar;				// set up to send Xon
sl@0
   636
		EnableTransmit();						// Make sure we are transmitting
sl@0
   637
		}
sl@0
   638
	}
sl@0
   639
sl@0
   640
TInt DChannelComm::SetRxBufferSize(TInt aSize)
sl@0
   641
//
sl@0
   642
// Set the receive buffer size.
sl@0
   643
//
sl@0
   644
	{
sl@0
   645
	LOG(("SetRxBufferSize(aSize=0x%X)", aSize));
sl@0
   646
	aSize=(aSize+3)&~3;
sl@0
   647
	TUint8 *newBuf=(TUint8*)Kern::ReAlloc(iRxCharBuf,aSize<<1);
sl@0
   648
	if (!newBuf)
sl@0
   649
		return KErrNoMemory;
sl@0
   650
	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
   651
	iRxCharBuf=newBuf;
sl@0
   652
	iRxErrorBuf=newBuf+aSize;
sl@0
   653
	iRxBufSize=aSize;
sl@0
   654
	iFlowControlLowerThreshold=aSize>>2;
sl@0
   655
	iFlowControlUpperThreshold=3*aSize>>2;
sl@0
   656
	iRxDrainThreshold=aSize>>1;
sl@0
   657
	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   658
	ResetBuffers(EFalse);
sl@0
   659
	return KErrNone;
sl@0
   660
	}
sl@0
   661
sl@0
   662
TInt DChannelComm::TurnaroundSet(TUint aNewTurnaroundMilliSeconds)
sl@0
   663
	{
sl@0
   664
	LOG(("TurnaroundSet(val=0x%X)", aNewTurnaroundMilliSeconds));
sl@0
   665
	TInt r = KErrNone;
sl@0
   666
	iTurnaroundMinMilliSeconds = aNewTurnaroundMilliSeconds;
sl@0
   667
	return r;
sl@0
   668
	}
sl@0
   669
sl@0
   670
TBool DChannelComm::TurnaroundStopTimer()
sl@0
   671
// Stop the timer and DFC
sl@0
   672
	{
sl@0
   673
	LOG(("TurnaroundStopTimer()"));
sl@0
   674
	
sl@0
   675
	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
   676
	TBool result = iTurnaroundTimerRunning;
sl@0
   677
	if(result)
sl@0
   678
		iTurnaroundTimerRunning = EFalse;	
sl@0
   679
	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   680
sl@0
   681
	if (result)
sl@0
   682
		{
sl@0
   683
		iTurnaroundTimer.Cancel();
sl@0
   684
		iTurnaroundDfc.Cancel();
sl@0
   685
		}
sl@0
   686
	return result;
sl@0
   687
	}
sl@0
   688
sl@0
   689
TInt DChannelComm::TurnaroundClear()
sl@0
   690
// Clear any old timer and start timer based on new turnaround timer
sl@0
   691
// Called for any change: from T > 0 to T == 0 or (T = t1 > 0) to (T = t2 > 0)
sl@0
   692
// POLICY: If a write has already been delayed, it will be started immediately if the requested 
sl@0
   693
// turnaround time is elapsed else will only start after it is elapsed.
sl@0
   694
	{
sl@0
   695
	LOG(("TurnaroundClear()"));
sl@0
   696
	TInt r = KErrNone;
sl@0
   697
	TUint delta = 0;
sl@0
   698
sl@0
   699
	if(iTurnaroundTimerStartTimeValid == 1)
sl@0
   700
		{
sl@0
   701
		//Calculate the turnaround time elapsed so far.
sl@0
   702
		delta = (NKern::TickCount() - iTurnaroundTimerStartTime) * NKern::TickPeriod();
sl@0
   703
		}
sl@0
   704
    if(delta < iTurnaroundMicroSeconds)
sl@0
   705
		{
sl@0
   706
        iTurnaroundMinMilliSeconds = (iTurnaroundMicroSeconds - delta)/1000;
sl@0
   707
        iTurnaroundTimerStartTimeValid = 3; //Just to make sure that the turnaround timer start time is not captured.
sl@0
   708
        RestartTurnaroundTimer();
sl@0
   709
		}
sl@0
   710
    else
sl@0
   711
		{
sl@0
   712
		if(TurnaroundStopTimer())
sl@0
   713
			{
sl@0
   714
			// if a write is waiting, start a DFC to run it
sl@0
   715
			TurnaroundStartDfcImplementation(EFalse);
sl@0
   716
			}
sl@0
   717
		}
sl@0
   718
	iTurnaroundMinMilliSeconds = 0;
sl@0
   719
	return r;
sl@0
   720
	}
sl@0
   721
sl@0
   722
TInt DChannelComm::RestartTurnaroundTimer()
sl@0
   723
	{
sl@0
   724
	LOG(("RestartTurnaroundTimer()"));
sl@0
   725
	TInt r=KErrNone;
sl@0
   726
sl@0
   727
	// POLICY: if timer is running from a previous read, stop it and re-start it
sl@0
   728
	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
   729
	TBool cancelDfcs = (iTurnaroundMinMilliSeconds > 0) && iTurnaroundTimerRunning;
sl@0
   730
	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   731
	if (cancelDfcs) 
sl@0
   732
		{
sl@0
   733
		iTurnaroundTimer.Cancel();
sl@0
   734
		iTurnaroundDfc.Cancel();
sl@0
   735
		}
sl@0
   736
sl@0
   737
	// Start the timer & update driver state to reflect that the timer is running
sl@0
   738
	TInt timeout = 0;
sl@0
   739
	irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
   740
	if(iTurnaroundMinMilliSeconds > 0)
sl@0
   741
		{
sl@0
   742
		iTurnaroundTimerRunning = ETrue;
sl@0
   743
		timeout = NKern::TimerTicks(iTurnaroundMinMilliSeconds);
sl@0
   744
		//Record the time stamp of turnaround timer start
sl@0
   745
		if(iTurnaroundTimerStartTimeValid != 3)
sl@0
   746
		    iTurnaroundTimerStartTime = NKern::TickCount();
sl@0
   747
		iTurnaroundTimerStartTimeValid = 1;
sl@0
   748
		}
sl@0
   749
	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   750
	if (timeout)
sl@0
   751
		r=iTurnaroundTimer.OneShot(timeout);
sl@0
   752
	return r;
sl@0
   753
	}
sl@0
   754
sl@0
   755
void DChannelComm::TurnaroundStartDfc(TAny* aSelf)
sl@0
   756
	{
sl@0
   757
	DChannelComm* self = (DChannelComm*)aSelf;
sl@0
   758
	self->TurnaroundStartDfcImplementation(ETrue);		// in ISR so Irqs are already disabled
sl@0
   759
	}
sl@0
   760
sl@0
   761
void DChannelComm::TurnaroundStartDfcImplementation(TBool aInIsr)
sl@0
   762
	{
sl@0
   763
	LOG(("TurnaroundStartDfcImplementation(inIsr=%d)", aInIsr));
sl@0
   764
	TInt irq=0;
sl@0
   765
    if(!aInIsr)
sl@0
   766
		irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
   767
	else 
sl@0
   768
		__SPIN_LOCK(iLock);
sl@0
   769
sl@0
   770
	iTurnaroundTimerRunning = EFalse;
sl@0
   771
	if(iTurnaroundTransmitDelayed || iTurnaroundBreakDelayed)
sl@0
   772
		{
sl@0
   773
        if(aInIsr)
sl@0
   774
			iTurnaroundDfc.Add();
sl@0
   775
		else
sl@0
   776
			{
sl@0
   777
			if(!aInIsr)
sl@0
   778
				__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   779
			else 
sl@0
   780
				__SPIN_UNLOCK(iLock);
sl@0
   781
			iTurnaroundDfc.Enque();
sl@0
   782
			return;
sl@0
   783
			}
sl@0
   784
		}
sl@0
   785
    if(!aInIsr)
sl@0
   786
		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   787
	else 
sl@0
   788
		__SPIN_UNLOCK(iLock);
sl@0
   789
	}
sl@0
   790
sl@0
   791
void DChannelComm::TurnaroundTimeout(TAny* aSelf)
sl@0
   792
	{
sl@0
   793
	DChannelComm* self = (DChannelComm*)aSelf;
sl@0
   794
	self->TurnaroundTimeoutImplementation();
sl@0
   795
	}
sl@0
   796
sl@0
   797
void DChannelComm::TurnaroundTimeoutImplementation()
sl@0
   798
	{
sl@0
   799
	LOG(("TurnaroundTimeoutImplementation()"));
sl@0
   800
	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
   801
	
sl@0
   802
	if(iTurnaroundBreakDelayed)
sl@0
   803
		{
sl@0
   804
		iTurnaroundBreakDelayed=EFalse;
sl@0
   805
		if (iStatus==EClosed)
sl@0
   806
			{
sl@0
   807
            __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   808
			Complete(EBreak, KErrNotReady);
sl@0
   809
			return;
sl@0
   810
			}
sl@0
   811
		else if(IsLineFail(iFailSignals))	// have signals changed in the meantime?
sl@0
   812
			{
sl@0
   813
            __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   814
			Complete(EBreak, KErrCommsLineFail);	// protected -> changed in signals ISR
sl@0
   815
			return;
sl@0
   816
			}
sl@0
   817
		if (iTurnaroundTransmitDelayed)
sl@0
   818
			{
sl@0
   819
			//delay write by break instead of turnaround
sl@0
   820
			iBreakDelayedTx = ETrue;
sl@0
   821
			iTurnaroundTransmitDelayed=EFalse;
sl@0
   822
			}
sl@0
   823
		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   824
        BreakOn();
sl@0
   825
		}
sl@0
   826
	else if(iTurnaroundTransmitDelayed)
sl@0
   827
		{
sl@0
   828
		iTurnaroundTransmitDelayed = EFalse;		// protected -> prevent reentrant ISR
sl@0
   829
		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   830
		
sl@0
   831
		RestartDelayedTransmission();
sl@0
   832
		}
sl@0
   833
	else 
sl@0
   834
		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   835
	}
sl@0
   836
sl@0
   837
void DChannelComm::ResetBuffers(TBool aResetTx)
sl@0
   838
//
sl@0
   839
// Reset the receive and maybe the transmit buffer.
sl@0
   840
//
sl@0
   841
	{
sl@0
   842
	LOG(("ResetBuffers(aResetTx=%d)", aResetTx));
sl@0
   843
	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
   844
	iRxPutIndex=0;
sl@0
   845
	iRxGetIndex=0;
sl@0
   846
	iRxBufCompleteIndex=0;
sl@0
   847
	if (aResetTx)
sl@0
   848
		{
sl@0
   849
		iTxPutIndex=0;
sl@0
   850
		iTxGetIndex=0;
sl@0
   851
		}
sl@0
   852
	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
   853
sl@0
   854
	if (iStatus==EActive)
sl@0
   855
		ReleaseFlowControl();
sl@0
   856
	iInputHeld=EFalse;
sl@0
   857
	}
sl@0
   858
sl@0
   859
TInt DChannelComm::TransmitIsr()
sl@0
   860
//
sl@0
   861
// Return the next character to be transmitted to the ISR
sl@0
   862
//
sl@0
   863
	{
sl@0
   864
	TInt tChar=iJamChar;			// Look for control character to jam in
sl@0
   865
    if (tChar>=0)					// Control character to send
sl@0
   866
        {
sl@0
   867
		iJamChar=KTxNoChar;
sl@0
   868
		}
sl@0
   869
    else if (!iOutputHeld && iTxGetIndex!=iTxPutIndex)
sl@0
   870
        {
sl@0
   871
		// Get spinlock, disable interrupts to ensure we can reach the unlock 
sl@0
   872
		// statement. An FIQ before unlock that attempted to get lock would 
sl@0
   873
		// lead to CPU deadlock
sl@0
   874
		TInt irqstate = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
   875
		
sl@0
   876
		// output not held and buffer not empty, get next char
sl@0
   877
		tChar=iTxBuffer[iTxGetIndex++];
sl@0
   878
		if (iTxGetIndex==iTxBufSize)
sl@0
   879
			iTxGetIndex=0;
sl@0
   880
			
sl@0
   881
		__SPIN_UNLOCK_IRQRESTORE(iLock, irqstate);
sl@0
   882
		}
sl@0
   883
sl@0
   884
	return tChar;
sl@0
   885
	}
sl@0
   886
sl@0
   887
void DChannelComm::ReceiveIsr(TUint* aChar, TInt aCount, TInt aXonXoff)
sl@0
   888
//
sl@0
   889
// Handle received character block from the ISR.
sl@0
   890
// aChar points to received characters, aCount=number received,
sl@0
   891
// aXonXoff=1 if XON received, -1 if XOFF received, 0 if neither
sl@0
   892
//
sl@0
   893
	{
sl@0
   894
	if (aXonXoff>0)
sl@0
   895
		{
sl@0
   896
		iOutputHeld &= ~KXoffSignal;	// Mark output ok. for XON/XOFF
sl@0
   897
		if (iOutputHeld==0)
sl@0
   898
			EnableTransmit();
sl@0
   899
		}
sl@0
   900
	else if (aXonXoff<0)
sl@0
   901
		{
sl@0
   902
		iOutputHeld |= KXoffSignal;		// Mark output held for XON/XOFF
sl@0
   903
		}
sl@0
   904
	if (aCount==0)						// if only XON or XOFF received
sl@0
   905
		return;
sl@0
   906
sl@0
   907
	// Get spinlock, disable interrupts to ensure we can reach the unlock 
sl@0
   908
	// statement. An FIQ before unlock that attempted to get lock would 
sl@0
   909
	// lead to CPU deadlock
sl@0
   910
	TInt irqstate = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
   911
sl@0
   912
	TInt count = RxCount();
sl@0
   913
	iReceived++;
sl@0
   914
sl@0
   915
	// At or above the high water mark send xoff every other character
sl@0
   916
    if (count>=iFlowControlUpperThreshold && ((count&1)!=0 || aCount>1))
sl@0
   917
		AssertFlowControl();
sl@0
   918
sl@0
   919
	TUint* pE=aChar+aCount;
sl@0
   920
	TInt e=KErrNone;
sl@0
   921
	TInt i=iRxPutIndex;
sl@0
   922
	TInt g=iRxGetIndex;
sl@0
   923
	TInt s=iRxBufSize;
sl@0
   924
	g=g?g-1:s-1;
sl@0
   925
	TInt p=iRxOutstanding?-1:0;
sl@0
   926
    TInt thresh=iRxBufReq.iLen-iRxDesPos;
sl@0
   927
	while(aChar<pE)
sl@0
   928
		{
sl@0
   929
		TUint c=*aChar++;
sl@0
   930
sl@0
   931
		// Check for parity errors and replace char if so configured.
sl@0
   932
		if (c & KReceiveIsrParityError)
sl@0
   933
			{
sl@0
   934
			// Replace bad character
sl@0
   935
			if (iConfig.iParityError==KConfigParityErrorReplaceChar)
sl@0
   936
				c = c & ~(0xff|KReceiveIsrParityError) | iConfig.iParityErrorChar;
sl@0
   937
			// Ignore parity error
sl@0
   938
			if (iConfig.iParityError==KConfigParityErrorIgnore)
sl@0
   939
				c = c & ~KReceiveIsrParityError;
sl@0
   940
			}
sl@0
   941
		
sl@0
   942
		if (i!=g)
sl@0
   943
			{
sl@0
   944
			iRxCharBuf[i]=(TUint8)c;
sl@0
   945
			iRxErrorBuf[i]=(TUint8)(c>>24);
sl@0
   946
sl@0
   947
			if (c & KReceiveIsrMaskError)
sl@0
   948
				{
sl@0
   949
				__UART_RX_ERROR(c);
sl@0
   950
				if (c & KReceiveIsrOverrunError)
sl@0
   951
					e = KErrCommsOverrun;
sl@0
   952
				else if (c & KReceiveIsrBreakError)
sl@0
   953
					e = KErrCommsBreak;
sl@0
   954
				else if (c & KReceiveIsrFrameError)
sl@0
   955
					e = KErrCommsFrame;
sl@0
   956
				else if (c & KReceiveIsrParityError)
sl@0
   957
					e = KErrCommsParity;
sl@0
   958
				}
sl@0
   959
			count++;
sl@0
   960
			if (++i==s)
sl@0
   961
				i=0;
sl@0
   962
			if (p<0)
sl@0
   963
				{
sl@0
   964
				if (e || IsTerminator(TUint8(c)) || count==thresh)
sl@0
   965
					{
sl@0
   966
					// need to complete client request
sl@0
   967
					iRxError = e;
sl@0
   968
					p=i;
sl@0
   969
					}
sl@0
   970
				}
sl@0
   971
			}
sl@0
   972
		else
sl@0
   973
			{
sl@0
   974
			__OVERRUN();
sl@0
   975
			// buffer overrun, discard character
sl@0
   976
			e=KErrCommsOverrun;
sl@0
   977
sl@0
   978
			// make sure client is informed of overrun error
sl@0
   979
			iRxError=e;
sl@0
   980
sl@0
   981
			// discard remaining characters and complete
sl@0
   982
			p=i;
sl@0
   983
			break;
sl@0
   984
			}
sl@0
   985
		}
sl@0
   986
	iRxPutIndex=i;
sl@0
   987
sl@0
   988
	if (iRxOutstanding)
sl@0
   989
		{
sl@0
   990
		if (p>=0)
sl@0
   991
			{
sl@0
   992
			// need to complete client request
sl@0
   993
			iRxBufCompleteIndex=p;
sl@0
   994
			iRxOutstanding=EFalse;
sl@0
   995
            RxComplete();
sl@0
   996
			}
sl@0
   997
		else if (count>=iRxDrainThreshold)
sl@0
   998
			{
sl@0
   999
			// drain buffer but don't complete
sl@0
  1000
			DrainRxBuffer();
sl@0
  1001
			}
sl@0
  1002
		else if (iRxOneOrMore<0)
sl@0
  1003
			{
sl@0
  1004
			// doing read one or more - drain the buffer
sl@0
  1005
			// this will start the timer
sl@0
  1006
			iRxOneOrMore=1;
sl@0
  1007
			DrainRxBuffer();
sl@0
  1008
			}
sl@0
  1009
		}
sl@0
  1010
sl@0
  1011
	__SPIN_UNLOCK_IRQRESTORE(iLock, irqstate);
sl@0
  1012
sl@0
  1013
	if (iNotifyData)
sl@0
  1014
		{
sl@0
  1015
		iNotifyData=EFalse;
sl@0
  1016
        RxComplete();
sl@0
  1017
		}
sl@0
  1018
	}
sl@0
  1019
sl@0
  1020
void DChannelComm::CheckTxBuffer()
sl@0
  1021
	{
sl@0
  1022
	// if buffer count < threshold, fill from client buffer
sl@0
  1023
	TInt count=TxCount();
sl@0
  1024
    if (iTxOutstanding && iTxDesPos<iTxBufReq.iLen && count<iTxFillThreshold)
sl@0
  1025
		iTxFillDfc.Add();
sl@0
  1026
	else if (count==0)
sl@0
  1027
		{
sl@0
  1028
		// TX buffer is now empty - see if we need to complete anything
sl@0
  1029
		if (iTxOutstanding)
sl@0
  1030
			{
sl@0
  1031
            if (iTxBufReq.iLen==0)
sl@0
  1032
				{
sl@0
  1033
				// request was a zero-length write - complete if hardware flow control
sl@0
  1034
				// is not asserted
sl@0
  1035
				if ((~iSignals & iHoldSignals)==0)
sl@0
  1036
					{
sl@0
  1037
					iTxOutstanding=EFalse;
sl@0
  1038
                    TxComplete();
sl@0
  1039
					}
sl@0
  1040
				}
sl@0
  1041
			else
sl@0
  1042
				{
sl@0
  1043
				// request was normal TX - complete now if not doing early completion
sl@0
  1044
				if (!(iConfig.iHandshake&KConfigWriteBufferedComplete))
sl@0
  1045
					{
sl@0
  1046
					iTxOutstanding=EFalse;
sl@0
  1047
					TxComplete();
sl@0
  1048
					}
sl@0
  1049
				}
sl@0
  1050
			}
sl@0
  1051
		}
sl@0
  1052
	}
sl@0
  1053
sl@0
  1054
sl@0
  1055
//
sl@0
  1056
// Pdd callback
sl@0
  1057
//
sl@0
  1058
void DChannelComm::UpdateSignals(TUint aSignals)
sl@0
  1059
	{
sl@0
  1060
    __KTRACE_OPT(KHARDWARE,Kern::Printf("CommSig: Upd %08x",aSignals));
sl@0
  1061
    iSignals=(iSignals&~KDTEInputSignals)|(aSignals&KDTEInputSignals);
sl@0
  1062
    DoSigNotify();	
sl@0
  1063
	}
sl@0
  1064
sl@0
  1065
sl@0
  1066
sl@0
  1067
/**
sl@0
  1068
 Handle a state change from the PDD. Called in ISR or DFC context.
sl@0
  1069
 */
sl@0
  1070
void DChannelComm::StateIsr(TUint aSignals)
sl@0
  1071
    {
sl@0
  1072
    iSignals=(iSignals&~KDTEInputSignals)|(aSignals&KDTEInputSignals);
sl@0
  1073
    if (iSignalsReq->IsReady() && ((iSignals^iNotifiedSignals)&iSigNotifyMask) )
sl@0
  1074
        {
sl@0
  1075
        iSigNotifyDfc.Add();
sl@0
  1076
        }
sl@0
  1077
    if (IsLineFail(iFailSignals))
sl@0
  1078
        {
sl@0
  1079
        if (iRxOutstanding)
sl@0
  1080
            {
sl@0
  1081
            iRxError=KErrCommsLineFail;
sl@0
  1082
            iRxBufCompleteIndex=iRxPutIndex;
sl@0
  1083
            iRxOutstanding=EFalse;
sl@0
  1084
			RxComplete();				
sl@0
  1085
            }
sl@0
  1086
        if (iTxOutstanding)
sl@0
  1087
            {
sl@0
  1088
            iTxError = KErrCommsLineFail;
sl@0
  1089
            iTxOutstanding=EFalse;
sl@0
  1090
			TxComplete();
sl@0
  1091
			}
sl@0
  1092
        }
sl@0
  1093
sl@0
  1094
	//
sl@0
  1095
	// Now we must determine if output is to be held
sl@0
  1096
	//
sl@0
  1097
    TUint status = ~iSignals & iHoldSignals;
sl@0
  1098
    if (iOutputHeld & KXoffSignal)
sl@0
  1099
        status |= KXoffSignal;      // Leave the xon/xoff handshake bit
sl@0
  1100
sl@0
  1101
    LOG(("State - ISR - 0x%x",status));
sl@0
  1102
    iOutputHeld=status;             // record new flow control state
sl@0
  1103
    if (iTxGetIndex==iTxPutIndex)
sl@0
  1104
        {
sl@0
  1105
        // Tx buffer is empty
sl@0
  1106
        if (iTxOutstanding && iTxBufReq.iLen==0 && (status&~KXoffSignal)==0)
sl@0
  1107
            {
sl@0
  1108
            // if hardware flow control released, complete zero-length write
sl@0
  1109
            iTxOutstanding=EFalse;
sl@0
  1110
			TxComplete();
sl@0
  1111
			}
sl@0
  1112
        }
sl@0
  1113
    else if (status==0)
sl@0
  1114
        {
sl@0
  1115
        // Tx buffer not empty and flow control released, so restart transmission
sl@0
  1116
        LOG(("Calling LDD:EnTx"));
sl@0
  1117
        EnableTransmit();
sl@0
  1118
        }
sl@0
  1119
    }
sl@0
  1120
sl@0
  1121
// check if transmitter is flow controlled
sl@0
  1122
void DChannelComm::CheckOutputHeld()
sl@0
  1123
	{
sl@0
  1124
	iOutputHeld=(iOutputHeld & KXoffSignal) | (~iSignals & iHoldSignals);
sl@0
  1125
    LOG(("CheckOPH IOH = %d",iOutputHeld));
sl@0
  1126
	}
sl@0
  1127
sl@0
  1128
void DChannelComm::HandleMsg(TMessageBase* aMsg)
sl@0
  1129
	{
sl@0
  1130
sl@0
  1131
	if (iStandby)
sl@0
  1132
		{ // postpone message handling to transition from standby
sl@0
  1133
		iMsgHeld=ETrue;
sl@0
  1134
		return;
sl@0
  1135
		}
sl@0
  1136
sl@0
  1137
	TThreadMessage& m=*(TThreadMessage*)aMsg;
sl@0
  1138
	LOG(("HandleMsg(%x a1=%x, a2=%x)", m.iValue, m.Int1(), m.Int2()));
sl@0
  1139
	TInt id=m.iValue;
sl@0
  1140
	if (id==(TInt)ECloseMsg)
sl@0
  1141
		{
sl@0
  1142
		Shutdown();
sl@0
  1143
		iStatus = EClosed;
sl@0
  1144
		m.Complete(KErrNone, EFalse);
sl@0
  1145
		return;
sl@0
  1146
		}
sl@0
  1147
	else if (id==KMaxTInt)
sl@0
  1148
		{
sl@0
  1149
		// DoCancel
sl@0
  1150
		DoCancel(m.Int0());
sl@0
  1151
		m.Complete(KErrNone,ETrue);
sl@0
  1152
		return;
sl@0
  1153
		}
sl@0
  1154
sl@0
  1155
	if (id<0)
sl@0
  1156
		{
sl@0
  1157
		// DoRequest
sl@0
  1158
        DoRequest(~id,m.Ptr1(),m.Ptr2());
sl@0
  1159
		m.Complete(KErrNone,ETrue);
sl@0
  1160
		}
sl@0
  1161
	else
sl@0
  1162
		{
sl@0
  1163
		// DoControl
sl@0
  1164
		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
sl@0
  1165
		m.Complete(r,ETrue);
sl@0
  1166
		}
sl@0
  1167
	}
sl@0
  1168
sl@0
  1169
void DChannelComm::DoCancel(TInt aMask)
sl@0
  1170
//
sl@0
  1171
// Cancel an outstanding request.
sl@0
  1172
//
sl@0
  1173
	{
sl@0
  1174
	LOG(("DoCancel(%d)", aMask));
sl@0
  1175
	if (aMask & RBusDevComm::ERequestReadCancel)
sl@0
  1176
		{
sl@0
  1177
		TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  1178
		iRxOutstanding=EFalse;
sl@0
  1179
		iNotifyData=EFalse;
sl@0
  1180
		iRxDesPos=0;
sl@0
  1181
        iRxBufReq.iLen=0;
sl@0
  1182
		iRxError=KErrNone;
sl@0
  1183
		iRxOneOrMore=0;
sl@0
  1184
		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1185
		iRxCompleteDfc.Cancel();
sl@0
  1186
		iRxDrainDfc.Cancel();
sl@0
  1187
		iTimer.Cancel();
sl@0
  1188
		iTimerDfc.Cancel();
sl@0
  1189
		Complete(ERx,KErrCancel);
sl@0
  1190
		}
sl@0
  1191
	if (aMask & RBusDevComm::ERequestWriteCancel)
sl@0
  1192
		{
sl@0
  1193
		TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  1194
        iTurnaroundTransmitDelayed = EFalse;
sl@0
  1195
        iTxPutIndex=0;
sl@0
  1196
        iTxGetIndex=0;
sl@0
  1197
        iTxOutstanding=EFalse;
sl@0
  1198
        iTxDesPos=0;
sl@0
  1199
        iTxBufReq.iLen=0;
sl@0
  1200
		iTxError=KErrNone;
sl@0
  1201
		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1202
		iTxCompleteDfc.Cancel();
sl@0
  1203
		iTxFillDfc.Cancel();
sl@0
  1204
		Complete(ETx,KErrCancel);
sl@0
  1205
		}
sl@0
  1206
    if (aMask & RBusDevComm::ERequestNotifySignalChangeCancel)
sl@0
  1207
        {
sl@0
  1208
        iSigNotifyDfc.Cancel();
sl@0
  1209
        Complete(ESigChg,KErrCancel);
sl@0
  1210
        }
sl@0
  1211
    if (aMask & RBusDevComm::ERequestBreakCancel)
sl@0
  1212
		{
sl@0
  1213
	 	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  1214
		if (iTurnaroundBreakDelayed)
sl@0
  1215
			iTurnaroundBreakDelayed=EFalse;
sl@0
  1216
		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1217
sl@0
  1218
		iBreakDfc.Cancel();
sl@0
  1219
		iBreakTimer.Cancel();
sl@0
  1220
		FinishBreakImplementation(KErrCancel);
sl@0
  1221
		}
sl@0
  1222
	}
sl@0
  1223
sl@0
  1224
/**
sl@0
  1225
 Intercept messages in client context before they are sent to the DFC queue
sl@0
  1226
 */
sl@0
  1227
TInt DChannelComm::SendMsg(TMessageBase* aMsg)
sl@0
  1228
	{
sl@0
  1229
	TInt r = KErrNone;
sl@0
  1230
	TInt max;
sl@0
  1231
	TInt len = 0;
sl@0
  1232
	TThreadMessage* m = (TThreadMessage*)aMsg;
sl@0
  1233
sl@0
  1234
	// Handle ECloseMsg & Cancel
sl@0
  1235
    TInt id=aMsg->iValue;
sl@0
  1236
    if (id==(TInt)ECloseMsg || id==KMaxTInt)
sl@0
  1237
        {
sl@0
  1238
		LOG(("SendMsg(%s)", (id==KMaxTInt)?"Cancel":"ECloseMsg"));
sl@0
  1239
		// do nothing cos these are handled on the DFC side
sl@0
  1240
        }
sl@0
  1241
	
sl@0
  1242
	// Handle control messages that access user memory here in client context
sl@0
  1243
    else if (id >= 0) 
sl@0
  1244
		{
sl@0
  1245
		TAny* a1 = m->iArg[0];
sl@0
  1246
		switch (aMsg->iValue) 
sl@0
  1247
			{
sl@0
  1248
			case RBusDevComm::EControlConfig:
sl@0
  1249
				{			
sl@0
  1250
				LOG(("SendMsg(EControlConfig, %x)", a1));
sl@0
  1251
				TPtrC8 cfg((const TUint8*)&iConfig,sizeof(iConfig));
sl@0
  1252
				return Kern::ThreadDesWrite(iClient,a1,cfg,0,KTruncateToMaxLength,iClient);
sl@0
  1253
				}
sl@0
  1254
			case RBusDevComm::EControlSetConfig:
sl@0
  1255
				{
sl@0
  1256
				LOG(("SendMsg(EControlSetConfig, %x)", a1));
sl@0
  1257
				if (AreAnyPending()) 
sl@0
  1258
					; // r = ESetConfigWhileRequestPending;
sl@0
  1259
				else
sl@0
  1260
					r = Kern::PinVirtualMemory(iPinObjSetConfig, (TLinAddr)a1, sizeof(TCommConfigV01));
sl@0
  1261
				}
sl@0
  1262
				break;
sl@0
  1263
			case RBusDevComm::EControlCaps:
sl@0
  1264
				{
sl@0
  1265
				LOG(("SendMsg(EControlCaps, %x)", a1));
sl@0
  1266
				TCommCaps2 caps;
sl@0
  1267
				PddCaps(caps);
sl@0
  1268
				return Kern::ThreadDesWrite(iClient,a1,caps,0,KTruncateToMaxLength,iClient);
sl@0
  1269
				}
sl@0
  1270
			default:
sl@0
  1271
				// Allow other control messages to go to DFC thread
sl@0
  1272
				LOG(("SendMsg(Ctrl %d, %x)", aMsg->iValue, a1));
sl@0
  1273
				break;
sl@0
  1274
			}
sl@0
  1275
		}
sl@0
  1276
sl@0
  1277
sl@0
  1278
	// Handle requests
sl@0
  1279
	else 
sl@0
  1280
		{
sl@0
  1281
		TRequestStatus* status = (TRequestStatus*)m->iArg[0];
sl@0
  1282
		TAny* a1 = m->iArg[1];
sl@0
  1283
		TAny* a2 = m->iArg[2];
sl@0
  1284
		TInt reqNo = ~aMsg->iValue;
sl@0
  1285
		TInt irq;
sl@0
  1286
		switch (reqNo)
sl@0
  1287
			{
sl@0
  1288
			case RBusDevComm::ERequestRead:
sl@0
  1289
				{
sl@0
  1290
			    iNotifyData=EFalse;
sl@0
  1291
				// If client has *not* provided a buffer pointer, it means they only want
sl@0
  1292
				// to know when data becomes available.
sl@0
  1293
				if (!a1)
sl@0
  1294
					{
sl@0
  1295
					irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  1296
					TBool isEmpty = (iRxPutIndex==iRxGetIndex);
sl@0
  1297
					iNotifyData = isEmpty;
sl@0
  1298
					__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1299
					if (!isEmpty) // if Rx buffer has bytes in it we can complete the request immediately
sl@0
  1300
						{
sl@0
  1301
						Kern::RequestComplete(status, KErrNone);
sl@0
  1302
						return KErrNone;
sl@0
  1303
						}
sl@0
  1304
					// Do not start the Turnaround timer as this is not a Read request but a request for Data Available notification
sl@0
  1305
					LOG(("--Buf Empty--"));
sl@0
  1306
					}
sl@0
  1307
sl@0
  1308
				// Get buffer length if one has been given
sl@0
  1309
				if (a2)
sl@0
  1310
					r = Kern::ThreadRawRead(iClient,a2,&len,sizeof(len)); 
sl@0
  1311
sl@0
  1312
				// Check the client descriptor is valid and large enough to hold the required amount of data.
sl@0
  1313
				if (a1 && r==KErrNone) 
sl@0
  1314
					{
sl@0
  1315
					max = Kern::ThreadGetDesMaxLength(iClient, a1);
sl@0
  1316
					if (max<Abs(len) || max<0)
sl@0
  1317
						r = KErrGeneral; // do not start the Turnaround timer (invalid Descriptor this read never starts)
sl@0
  1318
					}
sl@0
  1319
sl@0
  1320
				LOG(("SendMsg(ERequestRead, %x, len=%d) max=%d r=%d", a1, len, max, r));
sl@0
  1321
sl@0
  1322
				// Set client descriptor length to zero & set up client buffer object
sl@0
  1323
				if (a1 && r==KErrNone) 
sl@0
  1324
					{
sl@0
  1325
					TPtrC8 p(NULL,0);
sl@0
  1326
					r = Kern::ThreadDesWrite(iClient,a1,p,0,0,iClient);
sl@0
  1327
					if (r == KErrNone)
sl@0
  1328
						r = iRxBufReq.Setup(status, a1, len);
sl@0
  1329
					}
sl@0
  1330
				}
sl@0
  1331
			break;
sl@0
  1332
sl@0
  1333
sl@0
  1334
			//
sl@0
  1335
			// ERequestWrite
sl@0
  1336
			//
sl@0
  1337
			case RBusDevComm::ERequestWrite:
sl@0
  1338
				if (iStatus==EClosed)
sl@0
  1339
					r = KErrNotReady;
sl@0
  1340
				else if (!a1) 
sl@0
  1341
					r = KErrArgument;
sl@0
  1342
				else 
sl@0
  1343
					r=Kern::ThreadRawRead(iClient, a2, &len, sizeof(len));
sl@0
  1344
				LOG(("SendMsg(ERequestWrite, %x, len=%d) r=%d", a1, len, r));
sl@0
  1345
sl@0
  1346
				// Setup pending client request for this write
sl@0
  1347
				if (r==KErrNone)
sl@0
  1348
					r = iTxBufReq.Setup(status, a1, len);		
sl@0
  1349
				break;
sl@0
  1350
sl@0
  1351
sl@0
  1352
			//
sl@0
  1353
			// ERequestBreak: a1 points to the number of microseconds to break for
sl@0
  1354
			//
sl@0
  1355
			case RBusDevComm::ERequestBreak:
sl@0
  1356
				r = Kern::ThreadRawRead(iClient, a1, &iBreakTimeMicroSeconds, sizeof(TInt));
sl@0
  1357
				if (r == KErrNone)
sl@0
  1358
					r = iBreakStatus->SetStatus(status);					
sl@0
  1359
				LOG(("SendMsg(ERequestBreak, %x) bktime=%d r=%d", a1, iBreakTimeMicroSeconds, r));
sl@0
  1360
				break;
sl@0
  1361
sl@0
  1362
sl@0
  1363
			//
sl@0
  1364
			// ERequestNotifySignalChange:	a1 points to user-side int to receive the signals bitmask
sl@0
  1365
			//								a2 points to the bitmask of signals the user is interested in
sl@0
  1366
			//
sl@0
  1367
			case RBusDevComm::ERequestNotifySignalChange:
sl@0
  1368
				LOG(("SendMsg(ERequestNotifySignalChange, %x, %x)", a1, a2));
sl@0
  1369
				if (!a1 || !a2)
sl@0
  1370
					{
sl@0
  1371
					r = KErrArgument;
sl@0
  1372
					break;
sl@0
  1373
					}
sl@0
  1374
				// Setup word-sized client buffer
sl@0
  1375
				r = Kern::ThreadRawRead(iClient,a2,&iSigNotifyMask,sizeof(TUint));
sl@0
  1376
				irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  1377
				if (r==KErrNone) 
sl@0
  1378
					{
sl@0
  1379
					r = iSignalsReq->SetStatus(status);
sl@0
  1380
					if (r==KErrNone) 
sl@0
  1381
						iSignalsReq->SetDestPtr(a1);
sl@0
  1382
					}
sl@0
  1383
				LOG(("ERequestNotifySignalChange: mask is %x, r is %d", iSigNotifyMask, r));
sl@0
  1384
				__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1385
				break;
sl@0
  1386
sl@0
  1387
sl@0
  1388
			// Unknown request
sl@0
  1389
			default:
sl@0
  1390
				LOG(("SendMsg(req %d, %x, %x)", reqNo, a1, a2));
sl@0
  1391
				r = KErrNotSupported;
sl@0
  1392
				break;
sl@0
  1393
sl@0
  1394
			}
sl@0
  1395
sl@0
  1396
			// If the request has an error, complete immediately
sl@0
  1397
			if (r!=KErrNone)
sl@0
  1398
				Kern::RequestComplete(status, r);
sl@0
  1399
		}
sl@0
  1400
sl@0
  1401
	// Send the client request to the DFC queue unless there's been an error
sl@0
  1402
	if (r==KErrNone)
sl@0
  1403
		r = DLogicalChannel::SendMsg(aMsg);
sl@0
  1404
	LOG(("<SendMsg ret %d", r));
sl@0
  1405
	return r;
sl@0
  1406
sl@0
  1407
	}
sl@0
  1408
sl@0
  1409
sl@0
  1410
/**
sl@0
  1411
 Handle asynchronous requests. Called in DFC context.
sl@0
  1412
 */
sl@0
  1413
void DChannelComm::DoRequest(TInt aReqNo, TAny* a1, TAny* a2)
sl@0
  1414
    {
sl@0
  1415
	LOG(("DoRequest(%d %x %x)", aReqNo, a1, a2));
sl@0
  1416
sl@0
  1417
    //
sl@0
  1418
    // First check if we have started
sl@0
  1419
    //
sl@0
  1420
    if (iStatus==EOpen)
sl@0
  1421
        {
sl@0
  1422
        Start();
sl@0
  1423
        CheckOutputHeld();
sl@0
  1424
        SetSignals(iAutoSignals,0);
sl@0
  1425
        LOG(("DReq- RFC"));
sl@0
  1426
        ReleaseFlowControl();
sl@0
  1427
        }
sl@0
  1428
    //
sl@0
  1429
    // Check for a line fail
sl@0
  1430
    //
sl@0
  1431
    if (IsLineFail(iFailSignals))
sl@0
  1432
		{
sl@0
  1433
		Complete(EAll, KErrCommsLineFail);
sl@0
  1434
		return;
sl@0
  1435
		}	
sl@0
  1436
sl@0
  1437
    //
sl@0
  1438
    // Now we can dispatch the async request
sl@0
  1439
    //
sl@0
  1440
    switch (aReqNo)
sl@0
  1441
        {
sl@0
  1442
        case RBusDevComm::ERequestRead:
sl@0
  1443
			InitiateRead(iRxBufReq.iLen);
sl@0
  1444
            break;
sl@0
  1445
sl@0
  1446
        case RBusDevComm::ERequestWrite:
sl@0
  1447
            {
sl@0
  1448
			
sl@0
  1449
			// See if we need to delay the write
sl@0
  1450
            TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  1451
			iTurnaroundTransmitDelayed = iTurnaroundTimerRunning!=0;
sl@0
  1452
			iBreakDelayedTx = (iFlags & KBreaking);
sl@0
  1453
			__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1454
sl@0
  1455
			// If we do need to delay the write
sl@0
  1456
            if (iTurnaroundTransmitDelayed || iBreakDelayedTx)
sl@0
  1457
                break;
sl@0
  1458
			
sl@0
  1459
			//
sl@0
  1460
			InitiateWrite();
sl@0
  1461
            break;
sl@0
  1462
            }
sl@0
  1463
sl@0
  1464
        case RBusDevComm::ERequestNotifySignalChange:
sl@0
  1465
            iNotifiedSignals = iSignals;
sl@0
  1466
			DoSigNotify();
sl@0
  1467
            break;
sl@0
  1468
            
sl@0
  1469
        case RBusDevComm::ERequestBreak:
sl@0
  1470
			if(iTurnaroundTimerRunning)
sl@0
  1471
				iTurnaroundBreakDelayed = ETrue;
sl@0
  1472
			else
sl@0
  1473
				BreakOn();
sl@0
  1474
			break;
sl@0
  1475
sl@0
  1476
        }
sl@0
  1477
    }
sl@0
  1478
sl@0
  1479
/**
sl@0
  1480
 Called in DFC context upon receipt of ERequestRead
sl@0
  1481
 */
sl@0
  1482
void DChannelComm::InitiateRead(TInt aLength)
sl@0
  1483
    {
sl@0
  1484
    LOG(("InitiateRead(%d)", aLength));
sl@0
  1485
    iRxOutstanding=EFalse;
sl@0
  1486
	iRxOneOrMore=0;
sl@0
  1487
sl@0
  1488
    // Complete zero-length read immediately
sl@0
  1489
    if (aLength==0)
sl@0
  1490
        {
sl@0
  1491
		iRxBufReq.Complete(iClient, KErrNone);
sl@0
  1492
        RestartTurnaroundTimer();
sl@0
  1493
        return;
sl@0
  1494
        }
sl@0
  1495
sl@0
  1496
	TBool length_negative = (aLength<0);
sl@0
  1497
	if (length_negative)
sl@0
  1498
		aLength = -aLength;
sl@0
  1499
	iRxBufReq.iLen=aLength;
sl@0
  1500
sl@0
  1501
    // If the RX buffer is empty, we must wait for more data
sl@0
  1502
    TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  1503
    if (iRxPutIndex==iRxGetIndex)
sl@0
  1504
        {
sl@0
  1505
		if (length_negative)
sl@0
  1506
            iRxOneOrMore=-1;        // -1 because timer not started
sl@0
  1507
        iRxOutstanding=ETrue;
sl@0
  1508
        __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1509
        return;
sl@0
  1510
        }
sl@0
  1511
    __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1512
sl@0
  1513
    // RX buffer contains characters, must scan buffer and then complete
sl@0
  1514
	if (length_negative)
sl@0
  1515
        {
sl@0
  1516
        // ReceiveOneOrMore, up to -aLength characters
sl@0
  1517
        iRxOneOrMore=1;
sl@0
  1518
        }
sl@0
  1519
    TInt getIndex=iRxGetIndex;
sl@0
  1520
    TInt count=0;
sl@0
  1521
    TUint stat=0;
sl@0
  1522
	TBool complete=EFalse;
sl@0
  1523
    while(!complete)
sl@0
  1524
        {
sl@0
  1525
        while(count<aLength && getIndex!=iRxPutIndex)
sl@0
  1526
            {
sl@0
  1527
            if ((stat=iRxErrorBuf[getIndex])!=0 || IsTerminator(iRxCharBuf[getIndex]))
sl@0
  1528
                {
sl@0
  1529
                // this character will complete the request
sl@0
  1530
                if (++getIndex==iRxBufSize)
sl@0
  1531
                    getIndex=0;
sl@0
  1532
                count++;
sl@0
  1533
                complete=ETrue;
sl@0
  1534
                break;
sl@0
  1535
                }
sl@0
  1536
            if (++getIndex==iRxBufSize)
sl@0
  1537
                getIndex=0;
sl@0
  1538
            count++;
sl@0
  1539
            }
sl@0
  1540
        if (count==aLength)
sl@0
  1541
            complete=ETrue;
sl@0
  1542
        if (!complete)
sl@0
  1543
            {
sl@0
  1544
            TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  1545
            if (getIndex==iRxPutIndex)
sl@0
  1546
                {
sl@0
  1547
                // not enough chars to complete request, so set up to wait for more
sl@0
  1548
                iRxOutstanding=ETrue;
sl@0
  1549
                __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1550
                if (count)
sl@0
  1551
                    DoDrainRxBuffer(getIndex);
sl@0
  1552
                return;
sl@0
  1553
                }
sl@0
  1554
            // more characters have arrived, loop again
sl@0
  1555
            __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1556
            }
sl@0
  1557
        }
sl@0
  1558
sl@0
  1559
    // can complete request right now
sl@0
  1560
    TInt e=KErrNone;
sl@0
  1561
    if (stat)
sl@0
  1562
        {
sl@0
  1563
        stat<<=24;
sl@0
  1564
        if (stat & KReceiveIsrOverrunError)
sl@0
  1565
            e = KErrCommsOverrun;
sl@0
  1566
        else if (stat & KReceiveIsrBreakError)
sl@0
  1567
	        e = KErrCommsBreak;
sl@0
  1568
        else if (stat & KReceiveIsrFrameError)
sl@0
  1569
            e = KErrCommsFrame;
sl@0
  1570
        else if (stat & KReceiveIsrParityError)
sl@0
  1571
            e = KErrCommsParity;
sl@0
  1572
        }
sl@0
  1573
    if (iRxError==KErrNone)
sl@0
  1574
        iRxError=e;
sl@0
  1575
    iRxBufCompleteIndex=getIndex;
sl@0
  1576
    DoCompleteRx();
sl@0
  1577
    }
sl@0
  1578
sl@0
  1579
/**
sl@0
  1580
 Called in DFC context to start a write or a delayed write
sl@0
  1581
 */
sl@0
  1582
void DChannelComm::InitiateWrite()
sl@0
  1583
    {
sl@0
  1584
    LOG(("InitiateWrite() len=%d", iTxBufReq.iLen));
sl@0
  1585
sl@0
  1586
sl@0
  1587
	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  1588
	iTxDesPos=0;
sl@0
  1589
	iTurnaroundTimerStartTime = 0;
sl@0
  1590
	iTurnaroundTimerStartTimeValid = 2;
sl@0
  1591
	if (~iSignals & iFailSignals)
sl@0
  1592
		{
sl@0
  1593
		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1594
		iTxBufReq.Complete(iClient, KErrCommsLineFail);
sl@0
  1595
		return;
sl@0
  1596
		}
sl@0
  1597
	if (iTxBufReq.iLen==0)
sl@0
  1598
		{
sl@0
  1599
		if (iTxPutIndex==iTxGetIndex && (~iSignals & iHoldSignals)==0)
sl@0
  1600
			{
sl@0
  1601
			__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1602
			iTxBufReq.Complete(iClient, KErrNone);
sl@0
  1603
			return;
sl@0
  1604
			}
sl@0
  1605
		}
sl@0
  1606
sl@0
  1607
	iTxOutstanding=ETrue;
sl@0
  1608
	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1609
	if (iTxBufReq.iLen!=0)
sl@0
  1610
		DoFillTxBuffer();
sl@0
  1611
	}
sl@0
  1612
sl@0
  1613
void DChannelComm::SigNotifyDfc(TAny* aPtr)
sl@0
  1614
	{
sl@0
  1615
	((DChannelComm*)aPtr)->DoSigNotify();
sl@0
  1616
	}
sl@0
  1617
sl@0
  1618
void DChannelComm::DoSigNotify()
sl@0
  1619
    {
sl@0
  1620
	// Atomically update iNotifiedSignals and prepare to signal
sl@0
  1621
	TBool do_notify = EFalse;
sl@0
  1622
    TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  1623
    TUint orig_sig=iNotifiedSignals;
sl@0
  1624
    if (iSignalsReq->IsReady() && ( iNotifiedSignals==0xffffffff || ((iSignals^iNotifiedSignals)&iSigNotifyMask) ) )
sl@0
  1625
        {
sl@0
  1626
        iNotifiedSignals=iSignals;
sl@0
  1627
        do_notify=ETrue;
sl@0
  1628
        }
sl@0
  1629
    __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1630
    __KTRACE_OPT(KHARDWARE,Kern::Printf("CommSig: Orig=%08x New %08x Mask %08x",orig_sig,iNotifiedSignals,iSigNotifyMask));
sl@0
  1631
    if (do_notify)
sl@0
  1632
        {
sl@0
  1633
        TUint changed=iSigNotifyMask;
sl@0
  1634
        if (orig_sig!=0xffffffff)
sl@0
  1635
            changed&=(orig_sig^iNotifiedSignals);
sl@0
  1636
        changed=(changed<<12)|(iNotifiedSignals&iSigNotifyMask);
sl@0
  1637
sl@0
  1638
		// Write the result back to client memory and complete the request
sl@0
  1639
		__KTRACE_OPT(KHARDWARE,Kern::Printf("CommSig: Notify %08x",changed));
sl@0
  1640
		LOG(("DoSigNotify: %08x",changed));
sl@0
  1641
		TUint& rr = iSignalsReq->Data();
sl@0
  1642
		rr = changed;
sl@0
  1643
		Kern::QueueRequestComplete(iClient, iSignalsReq, KErrNone);
sl@0
  1644
		}
sl@0
  1645
    }
sl@0
  1646
sl@0
  1647
sl@0
  1648
/**
sl@0
  1649
 Manually read and act on signals
sl@0
  1650
 */
sl@0
  1651
void DChannelComm::UpdateAndProcessSignals()
sl@0
  1652
    {
sl@0
  1653
    TUint signals=Signals();
sl@0
  1654
    TBool notify=EFalse;
sl@0
  1655
    TBool complete_rx=EFalse;
sl@0
  1656
    TBool complete_tx=EFalse;
sl@0
  1657
    TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  1658
    iSignals=(iSignals&~KDTEInputSignals)|(signals&KDTEInputSignals);
sl@0
  1659
    if (iSignalsReq->IsReady() && ((iSignals^iNotifiedSignals)&iSigNotifyMask) )
sl@0
  1660
        {
sl@0
  1661
        notify=ETrue;
sl@0
  1662
        }
sl@0
  1663
    if (IsLineFail(iFailSignals))
sl@0
  1664
        {
sl@0
  1665
        if (iRxOutstanding)
sl@0
  1666
            {
sl@0
  1667
            iRxError=KErrCommsLineFail;
sl@0
  1668
            iRxBufCompleteIndex=iRxPutIndex;
sl@0
  1669
            iRxOutstanding=EFalse;
sl@0
  1670
            complete_rx=ETrue;
sl@0
  1671
            }
sl@0
  1672
        if (iTxOutstanding)
sl@0
  1673
            {
sl@0
  1674
            iTxError = KErrCommsLineFail;
sl@0
  1675
            iTxOutstanding=EFalse;
sl@0
  1676
            complete_tx=ETrue;
sl@0
  1677
            }
sl@0
  1678
        }
sl@0
  1679
    //
sl@0
  1680
    // Now we must determine if output is to be held
sl@0
  1681
    //
sl@0
  1682
    TUint status = ~iSignals & iHoldSignals;
sl@0
  1683
    if (iOutputHeld & KXoffSignal)
sl@0
  1684
        status |= KXoffSignal;      // Leave the xon/xoff handshake bit
sl@0
  1685
sl@0
  1686
    iOutputHeld=status;             // record new flow control state
sl@0
  1687
    if (iTxGetIndex==iTxPutIndex)
sl@0
  1688
        {
sl@0
  1689
        // Tx buffer is empty
sl@0
  1690
        if (iTxOutstanding && iTxBufReq.iLen==0 && (status&~KXoffSignal)==0)
sl@0
  1691
            {
sl@0
  1692
            // if hardware flow control released, complete zero-length write
sl@0
  1693
            iTxOutstanding=EFalse;
sl@0
  1694
            complete_tx=ETrue;
sl@0
  1695
            }
sl@0
  1696
        }
sl@0
  1697
    else if (status==0)
sl@0
  1698
        {
sl@0
  1699
        // Tx buffer not empty and flow control released, so restart transmission
sl@0
  1700
        EnableTransmit();
sl@0
  1701
        }
sl@0
  1702
    __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1703
    if (notify)
sl@0
  1704
        DoSigNotify();
sl@0
  1705
    if (complete_rx)
sl@0
  1706
        DoCompleteRx();
sl@0
  1707
    if (complete_tx)
sl@0
  1708
        DoCompleteTx();
sl@0
  1709
    }
sl@0
  1710
sl@0
  1711
sl@0
  1712
TUint DChannelComm::FailSignals(TUint aHandshake)
sl@0
  1713
	{
sl@0
  1714
	TUint r=0;
sl@0
  1715
	if ((aHandshake&(KConfigObeyCTS|KConfigFailCTS))==(KConfigObeyCTS|KConfigFailCTS))
sl@0
  1716
		r|=KSignalCTS;
sl@0
  1717
	if ((aHandshake&(KConfigObeyDSR|KConfigFailDSR))==(KConfigObeyDSR|KConfigFailDSR))
sl@0
  1718
		r|=KSignalDSR;
sl@0
  1719
	if ((aHandshake&(KConfigObeyDCD|KConfigFailDCD))==(KConfigObeyDCD|KConfigFailDCD))
sl@0
  1720
		r|=KSignalDCD;
sl@0
  1721
	return r;
sl@0
  1722
	}
sl@0
  1723
sl@0
  1724
TUint DChannelComm::HoldSignals(TUint aHandshake)
sl@0
  1725
	{
sl@0
  1726
	TUint r=0;
sl@0
  1727
	if (aHandshake & KConfigObeyCTS)
sl@0
  1728
		r|=KSignalCTS;
sl@0
  1729
	if (aHandshake & KConfigObeyDSR)
sl@0
  1730
		r|=KSignalDSR;
sl@0
  1731
	if (aHandshake & KConfigObeyDCD)
sl@0
  1732
		r|=KSignalDCD;
sl@0
  1733
	return r;
sl@0
  1734
	}
sl@0
  1735
sl@0
  1736
TUint DChannelComm::FlowControlSignals(TUint aHandshake)
sl@0
  1737
	{
sl@0
  1738
	TUint r=0;
sl@0
  1739
	if (!(aHandshake & KConfigFreeRTS))
sl@0
  1740
		r|=KSignalRTS;
sl@0
  1741
	else if (!(aHandshake & KConfigFreeDTR))
sl@0
  1742
		r|=KSignalDTR;
sl@0
  1743
	return r;
sl@0
  1744
	}
sl@0
  1745
sl@0
  1746
TUint DChannelComm::AutoSignals(TUint aHandshake)
sl@0
  1747
	{
sl@0
  1748
	TUint r=0;
sl@0
  1749
	if (!(aHandshake & KConfigFreeRTS) && !(aHandshake & KConfigFreeDTR))
sl@0
  1750
		r|=KSignalDTR;
sl@0
  1751
	return r;
sl@0
  1752
	}
sl@0
  1753
sl@0
  1754
TInt DChannelComm::SetConfig(TCommConfigV01& c)
sl@0
  1755
	{
sl@0
  1756
	LOG(("SetConfig(...)"));
sl@0
  1757
	TBool restart = EFalse;
sl@0
  1758
	TBool purge = EFalse;
sl@0
  1759
	TBool changeTerminators=EFalse;
sl@0
  1760
	TInt irq;
sl@0
  1761
	TInt r;
sl@0
  1762
sl@0
  1763
	if(c.iTerminatorCount>KConfigMaxTerminators)
sl@0
  1764
		return KErrNotSupported;
sl@0
  1765
	if ((r=ValidateConfig(c))!=KErrNone)
sl@0
  1766
		return r;
sl@0
  1767
	TUint failSignals=FailSignals(c.iHandshake);
sl@0
  1768
	if (IsLineFail(failSignals))
sl@0
  1769
		return KErrCommsLineFail;
sl@0
  1770
	if (iConfig.iRate != c.iRate
sl@0
  1771
		|| iConfig.iDataBits != c.iDataBits
sl@0
  1772
		|| iConfig.iStopBits != c.iStopBits
sl@0
  1773
		|| iConfig.iParity != c.iParity
sl@0
  1774
		|| iConfig.iFifo != c.iFifo
sl@0
  1775
		|| iConfig.iSpecialRate != c.iSpecialRate
sl@0
  1776
		|| iConfig.iSIREnable != c.iSIREnable
sl@0
  1777
		|| iConfig.iSIRSettings != c.iSIRSettings)
sl@0
  1778
		{
sl@0
  1779
		restart = ETrue;
sl@0
  1780
		}
sl@0
  1781
	else if (iConfig.iParityErrorChar != c.iParityErrorChar
sl@0
  1782
		|| iConfig.iParityError != c.iParityError
sl@0
  1783
		|| iConfig.iXonChar != c.iXonChar
sl@0
  1784
		|| iConfig.iXoffChar != c.iXoffChar
sl@0
  1785
		|| (iConfig.iHandshake&(KConfigObeyXoff|KConfigSendXoff))
sl@0
  1786
			!= (c.iHandshake&(KConfigObeyXoff|KConfigSendXoff)))
sl@0
  1787
		{
sl@0
  1788
		purge = ETrue;
sl@0
  1789
		}
sl@0
  1790
	else
sl@0
  1791
		{
sl@0
  1792
		if (iConfig.iTerminatorCount==c.iTerminatorCount)
sl@0
  1793
			{
sl@0
  1794
			for (TInt i=0; i<iConfig.iTerminatorCount; i++)
sl@0
  1795
				{
sl@0
  1796
				if (iConfig.iTerminator[i]!=c.iTerminator[i])
sl@0
  1797
					{
sl@0
  1798
					changeTerminators=ETrue;
sl@0
  1799
					break;
sl@0
  1800
					}
sl@0
  1801
				}
sl@0
  1802
			}
sl@0
  1803
		else
sl@0
  1804
			changeTerminators=ETrue;
sl@0
  1805
		if (!changeTerminators && c.iHandshake == iConfig.iHandshake)
sl@0
  1806
			return r;	// nothing to do.
sl@0
  1807
		}
sl@0
  1808
	if (iStatus==EActive && (restart || purge))
sl@0
  1809
		{
sl@0
  1810
		SetSignals(0,iFlowControlSignals|iAutoSignals); // Drop RTS
sl@0
  1811
		Stop(EStopNormal);
sl@0
  1812
		iStatus=EOpen;
sl@0
  1813
		if(purge)
sl@0
  1814
			ResetBuffers(ETrue);
sl@0
  1815
		iConfig=c;
sl@0
  1816
		iFailSignals=failSignals;
sl@0
  1817
		iHoldSignals=HoldSignals(c.iHandshake);
sl@0
  1818
		iFlowControlSignals=FlowControlSignals(c.iHandshake);
sl@0
  1819
		iAutoSignals=AutoSignals(c.iHandshake);
sl@0
  1820
		Start();
sl@0
  1821
		CheckOutputHeld();
sl@0
  1822
		SetSignals(iFlowControlSignals|iAutoSignals,0); // Assert RTS
sl@0
  1823
		irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  1824
		}
sl@0
  1825
	else
sl@0
  1826
		{
sl@0
  1827
		irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  1828
		if(purge)
sl@0
  1829
			ResetBuffers(ETrue);
sl@0
  1830
		iConfig=c;
sl@0
  1831
		iFailSignals=failSignals;
sl@0
  1832
		iHoldSignals=HoldSignals(c.iHandshake);
sl@0
  1833
		iFlowControlSignals=FlowControlSignals(c.iHandshake);
sl@0
  1834
		iAutoSignals=AutoSignals(c.iHandshake);
sl@0
  1835
		}
sl@0
  1836
	if (iConfig.iHandshake&KConfigObeyXoff)
sl@0
  1837
		{
sl@0
  1838
		iRxXonChar=c.iXonChar;
sl@0
  1839
		iRxXoffChar=c.iXoffChar;
sl@0
  1840
		}
sl@0
  1841
	else
sl@0
  1842
		{
sl@0
  1843
		iRxXonChar=0xffffffff;
sl@0
  1844
		iRxXoffChar=0xffffffff;
sl@0
  1845
		iOutputHeld&=~KXoffSignal;
sl@0
  1846
		}
sl@0
  1847
	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  1848
	if (iStatus==EActive)
sl@0
  1849
		ReleaseFlowControl();
sl@0
  1850
sl@0
  1851
	// no request pending here, so no need to protect this against interrupts
sl@0
  1852
	if (restart || purge || changeTerminators)
sl@0
  1853
		{
sl@0
  1854
		memclr(iTerminatorMask, 32);
sl@0
  1855
		TInt i;
sl@0
  1856
		for (i=0; i<iConfig.iTerminatorCount; i++)
sl@0
  1857
			{
sl@0
  1858
			SetTerminator(iConfig.iTerminator[i]);
sl@0
  1859
			}
sl@0
  1860
		}
sl@0
  1861
	return r;
sl@0
  1862
	}
sl@0
  1863
sl@0
  1864
TInt DChannelComm::DoControl(TInt aFunction, TAny* a1, TAny* a2)
sl@0
  1865
//
sl@0
  1866
// Sync requests.
sl@0
  1867
//
sl@0
  1868
	{
sl@0
  1869
	LOG(("DoControl(aFunction=%d, a1=%x, a2=%x)", aFunction, a1, a2));
sl@0
  1870
sl@0
  1871
	TInt r=KErrNone;
sl@0
  1872
sl@0
  1873
	switch (aFunction)
sl@0
  1874
		{
sl@0
  1875
		case RBusDevComm::EControlSetConfig:
sl@0
  1876
			{
sl@0
  1877
			TCommConfigV01 c;
sl@0
  1878
			memclr(&c, sizeof(c));
sl@0
  1879
			TPtr8 cfg((TUint8*)&c,0,sizeof(c));
sl@0
  1880
			r=Kern::ThreadDesRead(iClient,a1,cfg,0,0);
sl@0
  1881
			if (r==KErrNone)
sl@0
  1882
				r=SetConfig(c);
sl@0
  1883
			}
sl@0
  1884
			Kern::UnpinVirtualMemory(iPinObjSetConfig);
sl@0
  1885
			break;
sl@0
  1886
sl@0
  1887
		case RBusDevComm::EControlSignals:
sl@0
  1888
			{
sl@0
  1889
			UpdateAndProcessSignals();
sl@0
  1890
			r=iSignals;
sl@0
  1891
			break;
sl@0
  1892
			}
sl@0
  1893
		case RBusDevComm::EControlSetSignals:
sl@0
  1894
			{
sl@0
  1895
			TUint set=(TUint)a1;
sl@0
  1896
			TUint clear=(TUint)a2;
sl@0
  1897
			if (set & clear)
sl@0
  1898
;//				Kern::PanicCurrentThread(_L("D32COMM"), ESetSignalsSetAndClear);
sl@0
  1899
			else
sl@0
  1900
				{
sl@0
  1901
				if (iStatus==EOpen)
sl@0
  1902
					{
sl@0
  1903
					Start();
sl@0
  1904
					if (!(iConfig.iHandshake & KConfigFreeDTR) && !(clear & KSignalDTR))
sl@0
  1905
						set|=KSignalDTR; // Assert DTR
sl@0
  1906
					if (!(iConfig.iHandshake & KConfigFreeRTS) && !(clear & KSignalRTS))
sl@0
  1907
						set|=KSignalRTS; // Assert RTS
sl@0
  1908
					if (iConfig.iHandshake & KConfigSendXoff)
sl@0
  1909
						iJamChar=iConfig.iXonChar;
sl@0
  1910
					iInputHeld = EFalse;
sl@0
  1911
					CheckOutputHeld();
sl@0
  1912
					}
sl@0
  1913
				__e32_atomic_axo_ord32(&iSignals, ~(clear|set), set);
sl@0
  1914
				SetSignals(set,clear);
sl@0
  1915
				}
sl@0
  1916
			break;
sl@0
  1917
			}
sl@0
  1918
		case RBusDevComm::EControlQueryReceiveBuffer:
sl@0
  1919
			r=RxCount();
sl@0
  1920
			break;
sl@0
  1921
		case RBusDevComm::EControlResetBuffers:
sl@0
  1922
			if (AreAnyPending())
sl@0
  1923
;//				Kern::PanicCurrentThread(_L("D32COMM"), EResetBuffers);
sl@0
  1924
			else
sl@0
  1925
				ResetBuffers(ETrue);
sl@0
  1926
			break;
sl@0
  1927
		case RBusDevComm::EControlReceiveBufferLength:
sl@0
  1928
			r=iRxBufSize;
sl@0
  1929
			break;
sl@0
  1930
sl@0
  1931
		case RBusDevComm::EControlSetReceiveBufferLength:
sl@0
  1932
			if (AreAnyPending())
sl@0
  1933
;//				iThread->Panic(_L("D32COMM"),ESetReceiveBufferLength);
sl@0
  1934
			else
sl@0
  1935
				r=SetRxBufferSize((TInt)a1);
sl@0
  1936
			break;
sl@0
  1937
		// ***************************************
sl@0
  1938
sl@0
  1939
		case RBusDevComm::EControlMinTurnaroundTime:
sl@0
  1940
			r = iTurnaroundMicroSeconds;			// used saved value
sl@0
  1941
			break;
sl@0
  1942
sl@0
  1943
		case RBusDevComm::EControlSetMinTurnaroundTime:
sl@0
  1944
				{
sl@0
  1945
				if (a1<0)
sl@0
  1946
					a1=(TAny*)0;
sl@0
  1947
				iTurnaroundMicroSeconds = (TUint)a1;			// save this
sl@0
  1948
				TUint newTurnaroundMilliSeconds = (TUint)a1/1000;	// convert to ms
sl@0
  1949
				if(newTurnaroundMilliSeconds != iTurnaroundMinMilliSeconds)
sl@0
  1950
					{
sl@0
  1951
                    // POLICY: if a new turnaround time is set before the previous running timer has expired 
sl@0
  1952
 					// then the timer is adjusted depending on the new value and if any
sl@0
  1953
                    // write request has been queued, transmission will proceed after the timer has expired.
sl@0
  1954
					if(iTurnaroundTimerStartTimeValid == 0)
sl@0
  1955
						{	
sl@0
  1956
						 iTurnaroundTimerStartTimeValid = 1;
sl@0
  1957
						 iTurnaroundTimerStartTime = NKern::TickCount();
sl@0
  1958
						}
sl@0
  1959
				    if(iTurnaroundTimerStartTimeValid != 2)
sl@0
  1960
						TurnaroundClear();
sl@0
  1961
					if(newTurnaroundMilliSeconds > 0)
sl@0
  1962
						{
sl@0
  1963
						r = TurnaroundSet(newTurnaroundMilliSeconds);
sl@0
  1964
						}
sl@0
  1965
					}
sl@0
  1966
				}
sl@0
  1967
			break;
sl@0
  1968
		default:
sl@0
  1969
			r=KErrNotSupported;
sl@0
  1970
			}
sl@0
  1971
		return(r);
sl@0
  1972
		}
sl@0
  1973
sl@0
  1974
void DChannelComm::DoPowerUp()
sl@0
  1975
//
sl@0
  1976
// Called at switch on and upon Opening.
sl@0
  1977
//
sl@0
  1978
    {
sl@0
  1979
	LOG(("DoPowerUp()"));
sl@0
  1980
	__KTRACE_OPT(KPOWER,Kern::Printf("DChannelComm::DoPowerUp()"));
sl@0
  1981
sl@0
  1982
	ResetBuffers(ETrue);
sl@0
  1983
	iRxOutstanding=EFalse;
sl@0
  1984
	iNotifyData=EFalse;
sl@0
  1985
	iTxOutstanding=EFalse;
sl@0
  1986
    iTxDesPos=0;
sl@0
  1987
    iFlags=0;
sl@0
  1988
sl@0
  1989
	// Cancel turnaround
sl@0
  1990
	iTurnaroundMinMilliSeconds = 0;
sl@0
  1991
	iTurnaroundTimerRunning = EFalse;
sl@0
  1992
	iTurnaroundTransmitDelayed = EFalse;
sl@0
  1993
sl@0
  1994
	// cancel any DFCs/timers
sl@0
  1995
	iRxDrainDfc.Cancel();
sl@0
  1996
	iRxCompleteDfc.Cancel();
sl@0
  1997
	iTxFillDfc.Cancel();
sl@0
  1998
	iTxCompleteDfc.Cancel();
sl@0
  1999
	iTimer.Cancel();
sl@0
  2000
	iTurnaroundTimer.Cancel();
sl@0
  2001
	iTurnaroundDfc.Cancel();
sl@0
  2002
	iTimerDfc.Cancel();
sl@0
  2003
	iSigNotifyDfc.Cancel();
sl@0
  2004
sl@0
  2005
	Complete(EAll, KErrAbort);
sl@0
  2006
	if (!Kern::PowerGood())
sl@0
  2007
		return;
sl@0
  2008
	TUint hand=iConfig.iHandshake;
sl@0
  2009
	if (hand&(KConfigFreeRTS|KConfigFreeDTR))
sl@0
  2010
		{
sl@0
  2011
		Start();
sl@0
  2012
		if (!Kern::PowerGood())
sl@0
  2013
			return;
sl@0
  2014
		if (hand&KConfigFreeRTS)
sl@0
  2015
			{
sl@0
  2016
			if (iSignals&KSignalRTS)
sl@0
  2017
				SetSignals(KSignalRTS,0);
sl@0
  2018
			else
sl@0
  2019
				SetSignals(0,KSignalRTS);
sl@0
  2020
			}
sl@0
  2021
		if (!Kern::PowerGood())
sl@0
  2022
			return;
sl@0
  2023
		if (hand&KConfigFreeDTR)
sl@0
  2024
			{
sl@0
  2025
			if (iSignals&KSignalDTR)
sl@0
  2026
				SetSignals(KSignalDTR,0);
sl@0
  2027
			else
sl@0
  2028
				SetSignals(0,KSignalDTR);
sl@0
  2029
			}
sl@0
  2030
		CheckOutputHeld();
sl@0
  2031
		}
sl@0
  2032
	else
sl@0
  2033
		{
sl@0
  2034
		if (iStatus==EActive)
sl@0
  2035
			iStatus=EOpen;
sl@0
  2036
		}
sl@0
  2037
	}
sl@0
  2038
sl@0
  2039
void DChannelComm::PowerUpDfc(TAny* aPtr)
sl@0
  2040
	{
sl@0
  2041
	
sl@0
  2042
	DChannelComm* d = (DChannelComm*)aPtr;
sl@0
  2043
	__PM_ASSERT(d->iStandby);
sl@0
  2044
	if (d->iStatus != EClosed)
sl@0
  2045
		d->DoPowerUp();
sl@0
  2046
	else
sl@0
  2047
		// There is racing Close(): driver was already closed (ECloseMsg) but the DPowerHandler was not destroyed yet.
sl@0
  2048
		{}
sl@0
  2049
	d->iStandby = EFalse;
sl@0
  2050
	d->iPowerHandler->PowerUpDone();
sl@0
  2051
	if (d->iMsgHeld)
sl@0
  2052
		{
sl@0
  2053
		__PM_ASSERT(d->iStatus != EClosed);
sl@0
  2054
		d->iMsgHeld = EFalse;
sl@0
  2055
		d->HandleMsg(d->iMsgQ.iMessage);
sl@0
  2056
		}
sl@0
  2057
	}
sl@0
  2058
sl@0
  2059
void DChannelComm::PowerDownDfc(TAny* aPtr)
sl@0
  2060
	{
sl@0
  2061
	DChannelComm* d = (DChannelComm*)aPtr;
sl@0
  2062
	__PM_ASSERT(!d->iStandby);
sl@0
  2063
	d->iStandby = ETrue;
sl@0
  2064
	if (d->iStatus != EClosed)
sl@0
  2065
		d->Shutdown();
sl@0
  2066
	else
sl@0
  2067
		// There is racing Close(): driver was already closed (ECloseMsg) but the DPowerHandler was not destroyed yet.
sl@0
  2068
		{}
sl@0
  2069
	d->iPowerHandler->PowerDownDone();
sl@0
  2070
	}
sl@0
  2071
sl@0
  2072
DCommPowerHandler::DCommPowerHandler(DChannelComm* aChannel)
sl@0
  2073
	:	DPowerHandler(KLddName), 
sl@0
  2074
		iChannel(aChannel)
sl@0
  2075
	{
sl@0
  2076
	}
sl@0
  2077
sl@0
  2078
void DCommPowerHandler::PowerUp()
sl@0
  2079
	{
sl@0
  2080
	iChannel->iPowerUpDfc.Enque();
sl@0
  2081
	}
sl@0
  2082
sl@0
  2083
void DCommPowerHandler::PowerDown(TPowerState)
sl@0
  2084
	{
sl@0
  2085
	iChannel->iPowerDownDfc.Enque();
sl@0
  2086
	}
sl@0
  2087
sl@0
  2088
void DChannelComm::FinishBreak(TAny* aSelf)
sl@0
  2089
	{
sl@0
  2090
	DChannelComm* self = (DChannelComm*)aSelf;
sl@0
  2091
	self->QueueFinishBreakDfc();
sl@0
  2092
	}
sl@0
  2093
sl@0
  2094
void DChannelComm::QueueFinishBreakDfc()
sl@0
  2095
	{
sl@0
  2096
	iBreakDfc.Enque();
sl@0
  2097
	}
sl@0
  2098
	
sl@0
  2099
	
sl@0
  2100
void DChannelComm::FinishBreakDfc(TAny* aSelf)
sl@0
  2101
	{
sl@0
  2102
	DChannelComm* self = (DChannelComm*)aSelf;
sl@0
  2103
	self->FinishBreakImplementation(KErrNone);
sl@0
  2104
	}
sl@0
  2105
sl@0
  2106
void DChannelComm::FinishBreakImplementation(TInt aError)
sl@0
  2107
	{
sl@0
  2108
	if (iStatus==EClosed)
sl@0
  2109
		{
sl@0
  2110
		Complete(EBreak, KErrNotReady);
sl@0
  2111
		}
sl@0
  2112
	else
sl@0
  2113
		{
sl@0
  2114
		BreakOff();
sl@0
  2115
		Complete(EBreak, aError);
sl@0
  2116
		}
sl@0
  2117
sl@0
  2118
	// re-setup transmission if needed, for writes after a break
sl@0
  2119
	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  2120
	if (iBreakDelayedTx)
sl@0
  2121
		{
sl@0
  2122
		iBreakDelayedTx = EFalse;		// protected -> prevent reentrant ISR
sl@0
  2123
		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  2124
sl@0
  2125
		RestartDelayedTransmission();
sl@0
  2126
		}
sl@0
  2127
	else
sl@0
  2128
		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  2129
	}
sl@0
  2130
void DChannelComm::RestartDelayedTransmission()
sl@0
  2131
	{
sl@0
  2132
	LOG(("RestartDelayedTransmission()"));
sl@0
  2133
	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  2134
	TBool completeTx=EFalse;
sl@0
  2135
	
sl@0
  2136
	iBreakDelayedTx = EFalse;		// protected -> prevent reentrant ISR
sl@0
  2137
	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  2138
sl@0
  2139
	if (iStatus==EClosed)
sl@0
  2140
		{
sl@0
  2141
		irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  2142
		iTxError = KErrNotReady;		// protected -> changed in signals ISR
sl@0
  2143
		completeTx = ETrue;
sl@0
  2144
		}
sl@0
  2145
sl@0
  2146
	else if(IsLineFail(iFailSignals))	// have signals changed in the meantime?
sl@0
  2147
		{
sl@0
  2148
		irq = __SPIN_LOCK_IRQSAVE(iLock);
sl@0
  2149
		iTxError = KErrCommsLineFail;	// protected -> changed in signals ISR
sl@0
  2150
		completeTx = ETrue;
sl@0
  2151
		}
sl@0
  2152
sl@0
  2153
	else
sl@0
  2154
		{
sl@0
  2155
		InitiateWrite();
sl@0
  2156
		}
sl@0
  2157
sl@0
  2158
sl@0
  2159
	if(completeTx)
sl@0
  2160
		{
sl@0
  2161
		iTxError = KErrNone;
sl@0
  2162
		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
sl@0
  2163
		Complete(ETx, iTxError);
sl@0
  2164
		}
sl@0
  2165
	}