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