os/kernelhwsrv/kernel/eka/drivers/ecomm/d_comm.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\drivers\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 	}