os/kernelhwsrv/kernel/eka/drivers/ecomm/d_comm.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/drivers/ecomm/d_comm.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,2165 @@
     1.4 +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// e32\drivers\ecomm\d_comm.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include <drivers/comm.h>
    1.22 +#include <kernel/kern_priv.h>
    1.23 +#include <e32hal.h>
    1.24 +#include <e32uid.h>
    1.25 +
    1.26 +// Logging
    1.27 +#define LOG_ON(x) Kern::Printf##x
    1.28 +#define LOG_OFF(x)
    1.29 +#define LOG		LOG_OFF
    1.30 +
    1.31 +
    1.32 +//#define __UART_RX_ERROR(x)    *(TUint*)0xfeedface=(x)
    1.33 +//#define __OVERRUN() *(TUint*)0xfaece5=0
    1.34 +
    1.35 +#define __UART_RX_ERROR(x)
    1.36 +#define __OVERRUN()
    1.37 +
    1.38 +_LIT(KLddName,"Comm");
    1.39 +
    1.40 +
    1.41 +const TUint KXoffSignal=0x80;
    1.42 +//
    1.43 +const TUint KBreaking=0x02;
    1.44 +const TUint KBreakPending=0x04;
    1.45 +//
    1.46 +enum TPanic
    1.47 +	{
    1.48 +	ESetConfigWhileRequestPending,
    1.49 +	ESetSignalsSetAndClear,
    1.50 +	EResetBuffers,
    1.51 +	ESetReceiveBufferLength,
    1.52 +	};
    1.53 +
    1.54 +DECLARE_STANDARD_LDD()
    1.55 +	{
    1.56 +	return new DDeviceComm;
    1.57 +	}
    1.58 +
    1.59 +DDeviceComm::DDeviceComm()
    1.60 +//
    1.61 +// Constructor
    1.62 +//
    1.63 +	{
    1.64 +	LOG(("DDeviceComm::DDeviceComm"));
    1.65 +	iParseMask=KDeviceAllowAll;
    1.66 +	iUnitsMask=0xffffffff; // Leave units decision to the PDD
    1.67 +	iVersion=TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
    1.68 +	}
    1.69 +
    1.70 +TInt DDeviceComm::Install()
    1.71 +//
    1.72 +// Install the device driver.
    1.73 +//
    1.74 +	{
    1.75 +	LOG(("DDeviceComm::Install"));
    1.76 +	return(SetName(&KLddName));
    1.77 +	}
    1.78 +
    1.79 +void DDeviceComm::GetCaps(TDes8& aDes) const
    1.80 +//
    1.81 +// Return the Comm capabilities.
    1.82 +//
    1.83 +	{
    1.84 +	LOG(("DDeviceComm::GetCaps"));
    1.85 +	TPckgBuf<TCapsDevCommV01> b;
    1.86 +	b().version=TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
    1.87 +	Kern::InfoCopy(aDes,b);
    1.88 +	}
    1.89 +
    1.90 +TInt DDeviceComm::Create(DLogicalChannelBase*& aChannel)
    1.91 +//
    1.92 +// Create a channel on the device.
    1.93 +//
    1.94 +	{
    1.95 +	LOG(("DDeviceComm::Create"));
    1.96 +	aChannel=new DChannelComm;
    1.97 +	return aChannel?KErrNone:KErrNoMemory;
    1.98 +	}
    1.99 +
   1.100 +DChannelComm::DChannelComm()
   1.101 +//
   1.102 +// Constructor
   1.103 +//
   1.104 +	:	iPowerUpDfc(DChannelComm::PowerUpDfc,this,3),
   1.105 +		iPowerDownDfc(DChannelComm::PowerDownDfc,this,3),
   1.106 +		iRxDrainDfc(DChannelComm::DrainRxDfc,this,2),
   1.107 +		iRxCompleteDfc(DChannelComm::CompleteRxDfc,this,2),
   1.108 +		iTxFillDfc(DChannelComm::FillTxDfc,this,2),
   1.109 +		iTxCompleteDfc(DChannelComm::CompleteTxDfc,this,2),
   1.110 +		iTimerDfc(DChannelComm::TimerDfcFn,this,3),
   1.111 +		iSigNotifyDfc(DChannelComm::SigNotifyDfc,this,2),
   1.112 +//		iTurnaroundMinMilliSeconds(0),
   1.113 +//		iTurnaroundTimerRunning(EFalse),
   1.114 +//		iTurnaroundTransmitDelayed(EFalse),
   1.115 +		iTurnaroundTimer(DChannelComm::TurnaroundStartDfc, this),
   1.116 +		iTurnaroundDfc(DChannelComm::TurnaroundTimeout, this, 2),
   1.117 +		iTimer(DChannelComm::MsCallBack,this),
   1.118 +		iBreakDfc(DChannelComm::FinishBreakDfc, this, 2),
   1.119 +		iLock(TSpinLock::EOrderGenericIrqLow3)
   1.120 +	{
   1.121 +	LOG(("DChannelComm"));
   1.122 +//
   1.123 +// Setup the default config
   1.124 +//
   1.125 +	iConfig.iRate=EBps9600;
   1.126 +	iConfig.iDataBits=EData8;
   1.127 +	iConfig.iStopBits=EStop1;
   1.128 +	iConfig.iParity=EParityNone;
   1.129 +	iConfig.iFifo=EFifoEnable;
   1.130 +	iConfig.iHandshake=KConfigObeyCTS;
   1.131 +	iConfig.iParityError=KConfigParityErrorFail;
   1.132 +	iConfig.iSIREnable=ESIRDisable;
   1.133 +//	iConfig.iTerminatorCount=0;
   1.134 +//	iConfig.iTerminator[0]=0;
   1.135 +//	iConfig.iTerminator[1]=0;
   1.136 +//	iConfig.iTerminator[2]=0;
   1.137 +//	iConfig.iTerminator[3]=0;
   1.138 +	iConfig.iXonChar=0x11; // XON
   1.139 +	iConfig.iXoffChar=0x13; // XOFF
   1.140 +//	iConfig.iSpecialRate=0;
   1.141 +//	iConfig.iParityErrorChar=0;
   1.142 +	iRxXonChar=0xffffffff;
   1.143 +	iRxXoffChar=0xffffffff;
   1.144 +	iStatus=EOpen;
   1.145 +//	iFlags=0;
   1.146 +//	iSignals=0;
   1.147 +//	iFailSignals=0;
   1.148 +//	iHoldSignals=0;
   1.149 +//	iFlowControlSignals=0;
   1.150 +//	iAutoSignals=0;
   1.151 +//	iTerminatorMask[0...31]=0;
   1.152 +//	iShutdown=EFalse;
   1.153 +//	iRxCharBuf=NULL;
   1.154 +//	iRxErrorBuf=NULL;
   1.155 +//	iRxPutIndex=0;
   1.156 +//	iRxGetIndex=0;
   1.157 +//	iRxBufSize=0;
   1.158 +//	iFlowControlLowerThreshold=0;
   1.159 +//	iFlowControlUpperThreshold=0;
   1.160 +//	iRxDrainThreshold=0;
   1.161 +//	iRxBufCompleteIndex=0;
   1.162 +//	iInputHeld=EFalse;
   1.163 +//	iRxClientBufReq=NULL;
   1.164 +//	iRxDesPos=0;
   1.165 +//	iRxLength=0;
   1.166 +//	iRxOutstanding=EFalse;
   1.167 +//	iRxError=KErrNone;
   1.168 +//	iTxBuffer=NULL;
   1.169 +//	iTxPutIndex=0;
   1.170 +//	iTxGetIndex=0;
   1.171 +//	iTxBufSize=0;
   1.172 +//	iTxFillThreshold=0;
   1.173 +	iOutputHeld=0;
   1.174 +	iJamChar=KTxNoChar;
   1.175 +//	iTxDesPtr=NULL;
   1.176 +//	iTxDesPos=0;
   1.177 +//	iTxDesLength=0;
   1.178 +//	iTxOutstanding=EFalse;
   1.179 +//	iTxError=KErrNone;
   1.180 +
   1.181 +//	iTimeout=10;
   1.182 +	iTimeout=NKern::TimerTicks(5);
   1.183 +	iClient=&Kern::CurrentThread();
   1.184 +	iClient->Open();
   1.185 +//	iSigNotifyMask=0;
   1.186 +//	iSignalsPtr=NULL;
   1.187 +//	iSigNotifyStatus=NULL;
   1.188 +	iBreakStatus=NULL;
   1.189 +	iNotifiedSignals=0xffffffff;
   1.190 +	iPinObjSetConfig=NULL;
   1.191 +	}
   1.192 +
   1.193 +DChannelComm::~DChannelComm()
   1.194 +//
   1.195 +// Destructor
   1.196 +//
   1.197 +	{
   1.198 +	LOG(("~DChannelComm"));
   1.199 +	if (iPowerHandler)
   1.200 +		{
   1.201 +		iPowerHandler->Remove(); 
   1.202 +		delete iPowerHandler;
   1.203 +		}
   1.204 +    if (iRxCharBuf)
   1.205 +        Kern::Free(iRxCharBuf);
   1.206 +    if (iTxBuffer)
   1.207 +        Kern::Free(iTxBuffer);
   1.208 +	if (iBreakStatus)
   1.209 +		Kern::DestroyClientRequest(iBreakStatus);
   1.210 +	if (iSignalsReq)
   1.211 +		Kern::DestroyClientRequest(iSignalsReq);
   1.212 +	if (iPinObjSetConfig)
   1.213 +		Kern::DestroyVirtualPinObject(iPinObjSetConfig);
   1.214 +	Kern::SafeClose((DObject*&)iClient, NULL);
   1.215 +	}
   1.216 +
   1.217 +
   1.218 +void DChannelComm::Complete(TInt aMask, TInt aReason)
   1.219 +	{
   1.220 +	LOG(("Complete(aMask=%x aReason=%d)", aMask, aReason));
   1.221 +	if (aMask & ERx)
   1.222 +		iRxBufReq.Complete(iClient, aReason);
   1.223 +	if (aMask & ETx)
   1.224 +		iTxBufReq.Complete(iClient, aReason);
   1.225 +	if (aMask & ESigChg)
   1.226 +		Kern::QueueRequestComplete(iClient, iSignalsReq, aReason);
   1.227 +	if ((aMask & EBreak) && iBreakStatus && iBreakStatus->IsReady())
   1.228 +		Kern::QueueRequestComplete(iClient, iBreakStatus, aReason);
   1.229 +	}
   1.230 +
   1.231 +TInt DChannelComm::Shutdown()
   1.232 +	{
   1.233 +	__KTRACE_OPT(KPOWER,Kern::Printf("DChannelComm::Shutdown()"));
   1.234 +	LOG(("Shutdown()"));
   1.235 +
   1.236 +    if (iStatus == EActive)
   1.237 +        Stop(EStopPwrDown);
   1.238 +
   1.239 +    Complete(EAll, KErrAbort);
   1.240 +
   1.241 +	// UART interrupts are disabled; must make sure DFCs are not queued.
   1.242 +	iRxDrainDfc.Cancel();
   1.243 +	iRxCompleteDfc.Cancel();
   1.244 +	iTxFillDfc.Cancel();
   1.245 +	iTxCompleteDfc.Cancel();
   1.246 +	iTimer.Cancel();
   1.247 +	iTurnaroundTimer.Cancel();
   1.248 +	iTurnaroundDfc.Cancel();
   1.249 +	iTimerDfc.Cancel();
   1.250 +	iSigNotifyDfc.Cancel();
   1.251 +	iPowerUpDfc.Cancel();
   1.252 +	iPowerDownDfc.Cancel();
   1.253 +	iBreakTimer.Cancel();
   1.254 +	iBreakDfc.Cancel();
   1.255 +	
   1.256 +	if (iPdd)
   1.257 +		SetSignals(0,iFlowControlSignals|iAutoSignals);
   1.258 +
   1.259 +	return KErrCompletion;
   1.260 +	}
   1.261 +
   1.262 +TInt DChannelComm::DoCreate(TInt aUnit, const TDesC8* /*anInfo*/, const TVersion &aVer)
   1.263 +//
   1.264 +// Create the channel from the passed info.
   1.265 +//
   1.266 +	{
   1.267 +	LOG(("DoCreate(aUnit=%d,...)", aUnit));
   1.268 +	if(!Kern::CurrentThreadHasCapability(ECapabilityCommDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by ECOMM.LDD (Comm Driver)")))
   1.269 +		return KErrPermissionDenied;
   1.270 +	if (!Kern::QueryVersionSupported(TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber),aVer))
   1.271 +		return KErrNotSupported;
   1.272 +
   1.273 +	// set up the correct DFC queue
   1.274 +	SetDfcQ(((DComm*)iPdd)->DfcQ(aUnit));
   1.275 +	iPowerUpDfc.SetDfcQ(iDfcQ);
   1.276 +	iPowerDownDfc.SetDfcQ(iDfcQ);
   1.277 +	iRxDrainDfc.SetDfcQ(iDfcQ);
   1.278 +	iRxCompleteDfc.SetDfcQ(iDfcQ);
   1.279 +	iTxFillDfc.SetDfcQ(iDfcQ);
   1.280 +	iTxCompleteDfc.SetDfcQ(iDfcQ);
   1.281 +	iTimerDfc.SetDfcQ(iDfcQ);
   1.282 +	iSigNotifyDfc.SetDfcQ(iDfcQ);
   1.283 +	iTurnaroundDfc.SetDfcQ(iDfcQ);
   1.284 +	iBreakDfc.SetDfcQ(iDfcQ);
   1.285 +	iMsgQ.Receive();
   1.286 +
   1.287 +	// initialise the TX buffer
   1.288 +	iTxBufSize=KTxBufferSize;
   1.289 +	iTxBuffer=(TUint8*)Kern::Alloc(iTxBufSize);
   1.290 +	if (!iTxBuffer)
   1.291 +		return KErrNoMemory;
   1.292 +	iTxFillThreshold=iTxBufSize>>1;
   1.293 +
   1.294 +	// initialise the RX buffer
   1.295 +	iRxBufSize=KDefaultRxBufferSize;
   1.296 +	iRxCharBuf=(TUint8*)Kern::Alloc(iRxBufSize<<1);
   1.297 +	if (!iRxCharBuf)
   1.298 +		return KErrNoMemory;
   1.299 +	iRxErrorBuf=iRxCharBuf+iRxBufSize;
   1.300 +	iFlowControlLowerThreshold=iRxBufSize>>2;
   1.301 +	iFlowControlUpperThreshold=3*iRxBufSize>>2;
   1.302 +	iRxDrainThreshold=iRxBufSize>>1;
   1.303 +
   1.304 +	// Create request objects
   1.305 +	TInt r = Kern::CreateClientDataRequest(iSignalsReq);
   1.306 +	if (r==KErrNone)
   1.307 +		r = Kern::CreateClientRequest(iBreakStatus);
   1.308 +	if (r==KErrNone)
   1.309 +		r = iRxBufReq.Create();
   1.310 +	if (r==KErrNone)
   1.311 +		r = iTxBufReq.Create();
   1.312 +	if (r==KErrNone)
   1.313 +		r = Kern::CreateVirtualPinObject(iPinObjSetConfig);
   1.314 +	if (r != KErrNone)
   1.315 +		return r;
   1.316 +
   1.317 +	((DComm *)iPdd)->iLdd=this;
   1.318 +	PddCheckConfig(iConfig);
   1.319 +	iFailSignals=FailSignals(iConfig.iHandshake);
   1.320 +	iHoldSignals=HoldSignals(iConfig.iHandshake);
   1.321 +	iFlowControlSignals=FlowControlSignals(iConfig.iHandshake);
   1.322 +	iAutoSignals=AutoSignals(iConfig.iHandshake);
   1.323 +
   1.324 +	// create the power handler
   1.325 +	iPowerHandler=new DCommPowerHandler(this);
   1.326 +	if (!iPowerHandler)
   1.327 +		return KErrNoMemory;
   1.328 +	iPowerHandler->Add();
   1.329 +	DoPowerUp();
   1.330 +
   1.331 +	return KErrNone;
   1.332 +	}
   1.333 +
   1.334 +TInt DChannelComm::RequestUserHandle(DThread* aThread, TOwnerType aType)
   1.335 +	{
   1.336 +	// Ensure that each channel can only be used by a single thread.
   1.337 +	return (aThread!=iClient) ?  KErrAccessDenied : KErrNone;
   1.338 +	}
   1.339 +
   1.340 +void DChannelComm::MsCallBack(TAny* aPtr)
   1.341 +	{
   1.342 +	// called from ISR when timer completes
   1.343 +	DChannelComm *pC=(DChannelComm*)aPtr;
   1.344 +	pC->iTimerDfc.Add();
   1.345 +	}
   1.346 +
   1.347 +void DChannelComm::TimerDfcFn(TAny* aPtr)
   1.348 +	{
   1.349 +	DChannelComm *pC=(DChannelComm*)aPtr;
   1.350 +	pC->TimerDfc();
   1.351 +	}
   1.352 +
   1.353 +void DChannelComm::TimerDfc()
   1.354 +	{
   1.355 +	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
   1.356 +	if (iRxOutstanding)
   1.357 +		{
   1.358 +		if (iRxGetIndex==iRxPutIndex)
   1.359 +			{
   1.360 +			// buffer empty after timeout period, so complete
   1.361 +			iRxBufCompleteIndex=iRxPutIndex;
   1.362 +			iRxOutstanding=EFalse;
   1.363 +			iRxOneOrMore=0;
   1.364 +			__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.365 +			DoCompleteRx();
   1.366 +			return;
   1.367 +			}
   1.368 +		// buffer not empty, so drain buffer and requeue timer
   1.369 +		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.370 +		DoDrainRxBuffer(iRxPutIndex);
   1.371 +		return;
   1.372 +		}
   1.373 +	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.374 +	}
   1.375 +
   1.376 +void DChannelComm::DrainRxDfc(TAny* aPtr)
   1.377 +	{
   1.378 +	DChannelComm *pC=(DChannelComm*)aPtr;
   1.379 +	pC->DoDrainRxBuffer(pC->iRxPutIndex);
   1.380 +	}
   1.381 +
   1.382 +// Drain RX buffer in a DFC
   1.383 +void DChannelComm::DoDrainRxBuffer(TInt aEndIndex)
   1.384 +	{
   1.385 +	// if RX completion DFC is queued, leave buffer draining to it
   1.386 +	if (iRxCompleteDfc.Queued())
   1.387 +		return;
   1.388 +
   1.389 +	LOG(("DoDrainRxBuffer(aEndIndex=%d) iRxDesPos=%d iRxBufReq.iLen=%d", aEndIndex, iRxDesPos, iRxBufReq.iLen));
   1.390 +    
   1.391 +	// If there's an Rx request with bytes outstanding...
   1.392 +	if (iRxBufReq.iBuf && iRxDesPos<iRxBufReq.iLen)
   1.393 +        {
   1.394 +        TInt space=iRxBufReq.iLen-iRxDesPos; // the amount of the client buffer left to fill
   1.395 +        TInt avail=aEndIndex-iRxGetIndex;	 // the amount of data in the Rx buffer to copy to the client buffer
   1.396 +        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)
   1.397 +            avail+=iRxBufSize;
   1.398 +        TInt len=Min(space,avail); // total number of bytes to drain
   1.399 +
   1.400 +		// Drain up to (but not beyond) the end of the Rx buffer
   1.401 +        TInt len1=Min(len,iRxBufSize-iRxGetIndex);  // number of bytes to the end of the buffer
   1.402 +        TPtrC8 des(iRxCharBuf+iRxGetIndex,len1);
   1.403 +
   1.404 +		TInt r = Kern::ThreadBufWrite(iClient, iRxBufReq.iBuf, des, iRxDesPos, KChunkShiftBy0, iClient);
   1.405 +        if (r != KErrNone)
   1.406 +            {
   1.407 +            iRxError=r;
   1.408 +            DoCompleteRx();
   1.409 +            return;
   1.410 +            }
   1.411 +
   1.412 +		// Update the client buffer offset and the Rx buffer read pointer with what we've done so far
   1.413 +        TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
   1.414 +        iRxDesPos += len1;
   1.415 +        iRxGetIndex+=len1;
   1.416 +        if (iRxGetIndex>=iRxBufSize)
   1.417 +            iRxGetIndex-=iRxBufSize;
   1.418 +        __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.419 +
   1.420 +		// If the data wraps around the end of the Rx buffer, now write out the second part
   1.421 +		// which starts at the beginning of the Rx buffer.
   1.422 +        len-=len1;
   1.423 +        if (len)
   1.424 +            {
   1.425 +            des.Set(iRxCharBuf,len);
   1.426 +			r=Kern::ThreadBufWrite(iClient, iRxBufReq.iBuf, des, iRxDesPos, KChunkShiftBy0, iClient);
   1.427 +            if (r != KErrNone)
   1.428 +                {
   1.429 +                iRxError=r;
   1.430 +                DoCompleteRx();
   1.431 +                return;
   1.432 +                }
   1.433 +
   1.434 +			// Update client buffer offset and Rx buffer read offset
   1.435 +            irq = __SPIN_LOCK_IRQSAVE(iLock);
   1.436 +            iRxDesPos += len;
   1.437 +            iRxGetIndex+=len;
   1.438 +            __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.439 +            }
   1.440 +
   1.441 +        // release flow control if necessary
   1.442 +        if (iInputHeld && RxCount()<=iFlowControlLowerThreshold)
   1.443 +            ReleaseFlowControl();
   1.444 +
   1.445 +        // if we are doing ReadOneOrMore, start the timer
   1.446 +        if (iRxOneOrMore>0)
   1.447 +            {
   1.448 +            iTimer.OneShot(iTimeout);
   1.449 +            }
   1.450 +        }
   1.451 +    }
   1.452 +
   1.453 +
   1.454 +void DChannelComm::RxComplete()
   1.455 +{
   1.456 +	if (NKern::CurrentContext()==NKern::EInterrupt)
   1.457 +		iRxCompleteDfc.Add();
   1.458 +	else
   1.459 +		DoCompleteRx();			
   1.460 +}
   1.461 +
   1.462 +
   1.463 +void DChannelComm::CompleteRxDfc(TAny* aPtr)
   1.464 +	{
   1.465 +	DChannelComm *pC=(DChannelComm*)aPtr;
   1.466 +	pC->DoCompleteRx();
   1.467 +	}
   1.468 +
   1.469 +void DChannelComm::DoCompleteRx()
   1.470 +	{
   1.471 +    LOG(("DoCompleteRx()"));
   1.472 +	if (iRxOneOrMore>0)
   1.473 +		iTimer.Cancel();
   1.474 +	if (iRxBufReq.iLen)
   1.475 +        {
   1.476 +        iRxOneOrMore=0;
   1.477 +        DoDrainRxBuffer(iRxBufCompleteIndex);
   1.478 +		iRxBufReq.Complete(iClient, iRxError);
   1.479 +		iRxDesPos=0;
   1.480 +
   1.481 +        iRxError=KErrNone;
   1.482 +        // start Turnaround timer (got here because it received all data, timed out on a ReadOneOrMore or was terminated
   1.483 +        // early by FailSignals)
   1.484 +        RestartTurnaroundTimer();
   1.485 +        }
   1.486 +    else
   1.487 +        {
   1.488 +        Complete(ERx,KErrNone);
   1.489 +        // do not start Turnaround (got here on a request Data Available Notification)
   1.490 +        }
   1.491 +    }
   1.492 +
   1.493 +
   1.494 +void DChannelComm::TxComplete()
   1.495 +{
   1.496 +	if (NKern::CurrentContext()==NKern::EInterrupt)
   1.497 +		iTxCompleteDfc.Add(); 
   1.498 +	else
   1.499 +		DoCompleteTx();			
   1.500 +}
   1.501 +
   1.502 +
   1.503 +void DChannelComm::FillTxDfc(TAny* aPtr)
   1.504 +	{
   1.505 +	DChannelComm *pC=(DChannelComm*)aPtr;
   1.506 +	pC->DoFillTxBuffer();
   1.507 +	}
   1.508 +
   1.509 +// Fill TX buffer in a DFC
   1.510 +void DChannelComm::DoFillTxBuffer()
   1.511 +	{
   1.512 +    LOG(("DFTB %d =%d",iTxDesPos,iTxBufReq.iLen));
   1.513 +	if (iTxBufReq.iBuf && iTxDesPos<iTxBufReq.iLen)
   1.514 +        {
   1.515 +        TInt space=iTxBufSize-TxCount()-1;
   1.516 +        TInt remaining=iTxBufReq.iLen-iTxDesPos;
   1.517 +        TInt len=Min(space,remaining);              // number of chars to transfer
   1.518 +        TInt len1=Min(len,iTxBufSize-iTxPutIndex);  // number of chars to wrap point
   1.519 +        TPtr8 des(iTxBuffer+iTxPutIndex,len1,len1);
   1.520 +        LOG(("DFTxB sp = %d rem = %d iOPH = %d",space, remaining,iOutputHeld));
   1.521 +		TInt r=Kern::ThreadBufRead(iClient, iTxBufReq.iBuf, des, iTxDesPos, KChunkShiftBy0);
   1.522 +        if (r != KErrNone)
   1.523 +            {
   1.524 +            iTxError=r;
   1.525 +            DoCompleteTx();
   1.526 +            return;
   1.527 +            }
   1.528 +
   1.529 +        TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
   1.530 +        iTxDesPos+=len1;
   1.531 +        iTxPutIndex+=len1;
   1.532 +        if (iTxPutIndex>=iTxBufSize)
   1.533 +            iTxPutIndex-=iTxBufSize;
   1.534 +        __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.535 +
   1.536 +        len-=len1;
   1.537 +        if (len)
   1.538 +            {
   1.539 +            des.Set(iTxBuffer,len,len);
   1.540 +			r=Kern::ThreadBufRead(iClient, iTxBufReq.iBuf, des, iTxDesPos, KChunkShiftBy0);
   1.541 +            if (r != KErrNone)
   1.542 +                {
   1.543 +                iTxError=r;
   1.544 +                DoCompleteTx();
   1.545 +                return;
   1.546 +                }
   1.547 +
   1.548 +            irq = __SPIN_LOCK_IRQSAVE(iLock);
   1.549 +            iTxDesPos+=len;
   1.550 +            iTxPutIndex+=len;
   1.551 +            __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.552 +            }
   1.553 +        if (iTxDesPos==iTxBufReq.iLen)
   1.554 +            {
   1.555 +            // we have used up the client descriptor
   1.556 +            if (iConfig.iHandshake & KConfigWriteBufferedComplete)
   1.557 +                {
   1.558 +                iTxOutstanding=EFalse;
   1.559 +                DoCompleteTx();
   1.560 +                }
   1.561 +            }
   1.562 +        // if TX buffer not empty and not flow controlled, make sure TX is enabled
   1.563 +        if (iTxPutIndex!=iTxGetIndex  && (!iOutputHeld))
   1.564 +            {
   1.565 +            LOG(("Calling - DoTxBuff->ETx"));
   1.566 +            EnableTransmit();
   1.567 +            }
   1.568 +        }
   1.569 +    }
   1.570 +
   1.571 +void DChannelComm::CompleteTxDfc(TAny* aPtr)
   1.572 +	{
   1.573 +	DChannelComm *pC=(DChannelComm*)aPtr;
   1.574 +	pC->DoCompleteTx();
   1.575 +	}
   1.576 +
   1.577 +void DChannelComm::DoCompleteTx()
   1.578 +	{
   1.579 +	Complete(ETx,iTxError);
   1.580 +	iTxError=KErrNone;
   1.581 +	}
   1.582 +
   1.583 +void DChannelComm::Start()
   1.584 +//
   1.585 +// Start the driver receiving.
   1.586 +//
   1.587 +	{
   1.588 +	LOG(("Start()"));
   1.589 +	if (iStatus!=EClosed)
   1.590 +		{
   1.591 +		PddConfigure(iConfig);
   1.592 +		PddStart();
   1.593 +		iStatus=EActive;
   1.594 +		if ((iConfig.iHandshake & KConfigSendXoff) && iJamChar>=0)
   1.595 +			EnableTransmit(); // Send XOn if there is one
   1.596 +		}
   1.597 +	}
   1.598 +
   1.599 +void DChannelComm::BreakOn()
   1.600 +//
   1.601 +// Start the driver breaking.
   1.602 +//
   1.603 +	{
   1.604 +	LOG(("BreakOn()"));
   1.605 +	iFlags&=(~KBreakPending);
   1.606 +	iFlags|=KBreaking;
   1.607 +	PddBreak(ETrue);
   1.608 +	iBreakTimer.OneShot(iBreakTimeMicroSeconds, DChannelComm::FinishBreak, this);
   1.609 +	}
   1.610 +
   1.611 +void DChannelComm::BreakOff()
   1.612 +//
   1.613 +// Stop the driver breaking.
   1.614 +//
   1.615 +	{
   1.616 +	LOG(("BreakOff()"));
   1.617 +	PddBreak(EFalse);
   1.618 +	iFlags&=(~(KBreakPending|KBreaking));
   1.619 +	}
   1.620 +
   1.621 +void DChannelComm::AssertFlowControl()
   1.622 +	{
   1.623 +	iInputHeld=ETrue;
   1.624 +	SetSignals(0,iFlowControlSignals);
   1.625 +	if (iConfig.iHandshake&KConfigSendXoff)		// Doing input XON/XOFF
   1.626 +		{
   1.627 +		iJamChar=iConfig.iXoffChar;				// set up to send Xoff
   1.628 +		EnableTransmit();						// Make sure we are transmitting
   1.629 +		}
   1.630 +	}
   1.631 +
   1.632 +void DChannelComm::ReleaseFlowControl()
   1.633 +	{
   1.634 +	iInputHeld=EFalse;
   1.635 +	SetSignals(iFlowControlSignals,0);
   1.636 +	if (iConfig.iHandshake&KConfigSendXoff)		// Doing input XON/XOFF
   1.637 +		{
   1.638 +		iJamChar=iConfig.iXonChar;				// set up to send Xon
   1.639 +		EnableTransmit();						// Make sure we are transmitting
   1.640 +		}
   1.641 +	}
   1.642 +
   1.643 +TInt DChannelComm::SetRxBufferSize(TInt aSize)
   1.644 +//
   1.645 +// Set the receive buffer size.
   1.646 +//
   1.647 +	{
   1.648 +	LOG(("SetRxBufferSize(aSize=0x%X)", aSize));
   1.649 +	aSize=(aSize+3)&~3;
   1.650 +	TUint8 *newBuf=(TUint8*)Kern::ReAlloc(iRxCharBuf,aSize<<1);
   1.651 +	if (!newBuf)
   1.652 +		return KErrNoMemory;
   1.653 +	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
   1.654 +	iRxCharBuf=newBuf;
   1.655 +	iRxErrorBuf=newBuf+aSize;
   1.656 +	iRxBufSize=aSize;
   1.657 +	iFlowControlLowerThreshold=aSize>>2;
   1.658 +	iFlowControlUpperThreshold=3*aSize>>2;
   1.659 +	iRxDrainThreshold=aSize>>1;
   1.660 +	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.661 +	ResetBuffers(EFalse);
   1.662 +	return KErrNone;
   1.663 +	}
   1.664 +
   1.665 +TInt DChannelComm::TurnaroundSet(TUint aNewTurnaroundMilliSeconds)
   1.666 +	{
   1.667 +	LOG(("TurnaroundSet(val=0x%X)", aNewTurnaroundMilliSeconds));
   1.668 +	TInt r = KErrNone;
   1.669 +	iTurnaroundMinMilliSeconds = aNewTurnaroundMilliSeconds;
   1.670 +	return r;
   1.671 +	}
   1.672 +
   1.673 +TBool DChannelComm::TurnaroundStopTimer()
   1.674 +// Stop the timer and DFC
   1.675 +	{
   1.676 +	LOG(("TurnaroundStopTimer()"));
   1.677 +	
   1.678 +	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
   1.679 +	TBool result = iTurnaroundTimerRunning;
   1.680 +	if(result)
   1.681 +		iTurnaroundTimerRunning = EFalse;	
   1.682 +	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.683 +
   1.684 +	if (result)
   1.685 +		{
   1.686 +		iTurnaroundTimer.Cancel();
   1.687 +		iTurnaroundDfc.Cancel();
   1.688 +		}
   1.689 +	return result;
   1.690 +	}
   1.691 +
   1.692 +TInt DChannelComm::TurnaroundClear()
   1.693 +// Clear any old timer and start timer based on new turnaround timer
   1.694 +// Called for any change: from T > 0 to T == 0 or (T = t1 > 0) to (T = t2 > 0)
   1.695 +// POLICY: If a write has already been delayed, it will be started immediately if the requested 
   1.696 +// turnaround time is elapsed else will only start after it is elapsed.
   1.697 +	{
   1.698 +	LOG(("TurnaroundClear()"));
   1.699 +	TInt r = KErrNone;
   1.700 +	TUint delta = 0;
   1.701 +
   1.702 +	if(iTurnaroundTimerStartTimeValid == 1)
   1.703 +		{
   1.704 +		//Calculate the turnaround time elapsed so far.
   1.705 +		delta = (NKern::TickCount() - iTurnaroundTimerStartTime) * NKern::TickPeriod();
   1.706 +		}
   1.707 +    if(delta < iTurnaroundMicroSeconds)
   1.708 +		{
   1.709 +        iTurnaroundMinMilliSeconds = (iTurnaroundMicroSeconds - delta)/1000;
   1.710 +        iTurnaroundTimerStartTimeValid = 3; //Just to make sure that the turnaround timer start time is not captured.
   1.711 +        RestartTurnaroundTimer();
   1.712 +		}
   1.713 +    else
   1.714 +		{
   1.715 +		if(TurnaroundStopTimer())
   1.716 +			{
   1.717 +			// if a write is waiting, start a DFC to run it
   1.718 +			TurnaroundStartDfcImplementation(EFalse);
   1.719 +			}
   1.720 +		}
   1.721 +	iTurnaroundMinMilliSeconds = 0;
   1.722 +	return r;
   1.723 +	}
   1.724 +
   1.725 +TInt DChannelComm::RestartTurnaroundTimer()
   1.726 +	{
   1.727 +	LOG(("RestartTurnaroundTimer()"));
   1.728 +	TInt r=KErrNone;
   1.729 +
   1.730 +	// POLICY: if timer is running from a previous read, stop it and re-start it
   1.731 +	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
   1.732 +	TBool cancelDfcs = (iTurnaroundMinMilliSeconds > 0) && iTurnaroundTimerRunning;
   1.733 +	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.734 +	if (cancelDfcs) 
   1.735 +		{
   1.736 +		iTurnaroundTimer.Cancel();
   1.737 +		iTurnaroundDfc.Cancel();
   1.738 +		}
   1.739 +
   1.740 +	// Start the timer & update driver state to reflect that the timer is running
   1.741 +	TInt timeout = 0;
   1.742 +	irq = __SPIN_LOCK_IRQSAVE(iLock);
   1.743 +	if(iTurnaroundMinMilliSeconds > 0)
   1.744 +		{
   1.745 +		iTurnaroundTimerRunning = ETrue;
   1.746 +		timeout = NKern::TimerTicks(iTurnaroundMinMilliSeconds);
   1.747 +		//Record the time stamp of turnaround timer start
   1.748 +		if(iTurnaroundTimerStartTimeValid != 3)
   1.749 +		    iTurnaroundTimerStartTime = NKern::TickCount();
   1.750 +		iTurnaroundTimerStartTimeValid = 1;
   1.751 +		}
   1.752 +	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.753 +	if (timeout)
   1.754 +		r=iTurnaroundTimer.OneShot(timeout);
   1.755 +	return r;
   1.756 +	}
   1.757 +
   1.758 +void DChannelComm::TurnaroundStartDfc(TAny* aSelf)
   1.759 +	{
   1.760 +	DChannelComm* self = (DChannelComm*)aSelf;
   1.761 +	self->TurnaroundStartDfcImplementation(ETrue);		// in ISR so Irqs are already disabled
   1.762 +	}
   1.763 +
   1.764 +void DChannelComm::TurnaroundStartDfcImplementation(TBool aInIsr)
   1.765 +	{
   1.766 +	LOG(("TurnaroundStartDfcImplementation(inIsr=%d)", aInIsr));
   1.767 +	TInt irq=0;
   1.768 +    if(!aInIsr)
   1.769 +		irq = __SPIN_LOCK_IRQSAVE(iLock);
   1.770 +	else 
   1.771 +		__SPIN_LOCK(iLock);
   1.772 +
   1.773 +	iTurnaroundTimerRunning = EFalse;
   1.774 +	if(iTurnaroundTransmitDelayed || iTurnaroundBreakDelayed)
   1.775 +		{
   1.776 +        if(aInIsr)
   1.777 +			iTurnaroundDfc.Add();
   1.778 +		else
   1.779 +			{
   1.780 +			if(!aInIsr)
   1.781 +				__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.782 +			else 
   1.783 +				__SPIN_UNLOCK(iLock);
   1.784 +			iTurnaroundDfc.Enque();
   1.785 +			return;
   1.786 +			}
   1.787 +		}
   1.788 +    if(!aInIsr)
   1.789 +		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.790 +	else 
   1.791 +		__SPIN_UNLOCK(iLock);
   1.792 +	}
   1.793 +
   1.794 +void DChannelComm::TurnaroundTimeout(TAny* aSelf)
   1.795 +	{
   1.796 +	DChannelComm* self = (DChannelComm*)aSelf;
   1.797 +	self->TurnaroundTimeoutImplementation();
   1.798 +	}
   1.799 +
   1.800 +void DChannelComm::TurnaroundTimeoutImplementation()
   1.801 +	{
   1.802 +	LOG(("TurnaroundTimeoutImplementation()"));
   1.803 +	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
   1.804 +	
   1.805 +	if(iTurnaroundBreakDelayed)
   1.806 +		{
   1.807 +		iTurnaroundBreakDelayed=EFalse;
   1.808 +		if (iStatus==EClosed)
   1.809 +			{
   1.810 +            __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.811 +			Complete(EBreak, KErrNotReady);
   1.812 +			return;
   1.813 +			}
   1.814 +		else if(IsLineFail(iFailSignals))	// have signals changed in the meantime?
   1.815 +			{
   1.816 +            __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.817 +			Complete(EBreak, KErrCommsLineFail);	// protected -> changed in signals ISR
   1.818 +			return;
   1.819 +			}
   1.820 +		if (iTurnaroundTransmitDelayed)
   1.821 +			{
   1.822 +			//delay write by break instead of turnaround
   1.823 +			iBreakDelayedTx = ETrue;
   1.824 +			iTurnaroundTransmitDelayed=EFalse;
   1.825 +			}
   1.826 +		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.827 +        BreakOn();
   1.828 +		}
   1.829 +	else if(iTurnaroundTransmitDelayed)
   1.830 +		{
   1.831 +		iTurnaroundTransmitDelayed = EFalse;		// protected -> prevent reentrant ISR
   1.832 +		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.833 +		
   1.834 +		RestartDelayedTransmission();
   1.835 +		}
   1.836 +	else 
   1.837 +		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.838 +	}
   1.839 +
   1.840 +void DChannelComm::ResetBuffers(TBool aResetTx)
   1.841 +//
   1.842 +// Reset the receive and maybe the transmit buffer.
   1.843 +//
   1.844 +	{
   1.845 +	LOG(("ResetBuffers(aResetTx=%d)", aResetTx));
   1.846 +	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
   1.847 +	iRxPutIndex=0;
   1.848 +	iRxGetIndex=0;
   1.849 +	iRxBufCompleteIndex=0;
   1.850 +	if (aResetTx)
   1.851 +		{
   1.852 +		iTxPutIndex=0;
   1.853 +		iTxGetIndex=0;
   1.854 +		}
   1.855 +	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
   1.856 +
   1.857 +	if (iStatus==EActive)
   1.858 +		ReleaseFlowControl();
   1.859 +	iInputHeld=EFalse;
   1.860 +	}
   1.861 +
   1.862 +TInt DChannelComm::TransmitIsr()
   1.863 +//
   1.864 +// Return the next character to be transmitted to the ISR
   1.865 +//
   1.866 +	{
   1.867 +	TInt tChar=iJamChar;			// Look for control character to jam in
   1.868 +    if (tChar>=0)					// Control character to send
   1.869 +        {
   1.870 +		iJamChar=KTxNoChar;
   1.871 +		}
   1.872 +    else if (!iOutputHeld && iTxGetIndex!=iTxPutIndex)
   1.873 +        {
   1.874 +		// Get spinlock, disable interrupts to ensure we can reach the unlock 
   1.875 +		// statement. An FIQ before unlock that attempted to get lock would 
   1.876 +		// lead to CPU deadlock
   1.877 +		TInt irqstate = __SPIN_LOCK_IRQSAVE(iLock);
   1.878 +		
   1.879 +		// output not held and buffer not empty, get next char
   1.880 +		tChar=iTxBuffer[iTxGetIndex++];
   1.881 +		if (iTxGetIndex==iTxBufSize)
   1.882 +			iTxGetIndex=0;
   1.883 +			
   1.884 +		__SPIN_UNLOCK_IRQRESTORE(iLock, irqstate);
   1.885 +		}
   1.886 +
   1.887 +	return tChar;
   1.888 +	}
   1.889 +
   1.890 +void DChannelComm::ReceiveIsr(TUint* aChar, TInt aCount, TInt aXonXoff)
   1.891 +//
   1.892 +// Handle received character block from the ISR.
   1.893 +// aChar points to received characters, aCount=number received,
   1.894 +// aXonXoff=1 if XON received, -1 if XOFF received, 0 if neither
   1.895 +//
   1.896 +	{
   1.897 +	if (aXonXoff>0)
   1.898 +		{
   1.899 +		iOutputHeld &= ~KXoffSignal;	// Mark output ok. for XON/XOFF
   1.900 +		if (iOutputHeld==0)
   1.901 +			EnableTransmit();
   1.902 +		}
   1.903 +	else if (aXonXoff<0)
   1.904 +		{
   1.905 +		iOutputHeld |= KXoffSignal;		// Mark output held for XON/XOFF
   1.906 +		}
   1.907 +	if (aCount==0)						// if only XON or XOFF received
   1.908 +		return;
   1.909 +
   1.910 +	// Get spinlock, disable interrupts to ensure we can reach the unlock 
   1.911 +	// statement. An FIQ before unlock that attempted to get lock would 
   1.912 +	// lead to CPU deadlock
   1.913 +	TInt irqstate = __SPIN_LOCK_IRQSAVE(iLock);
   1.914 +
   1.915 +	TInt count = RxCount();
   1.916 +	iReceived++;
   1.917 +
   1.918 +	// At or above the high water mark send xoff every other character
   1.919 +    if (count>=iFlowControlUpperThreshold && ((count&1)!=0 || aCount>1))
   1.920 +		AssertFlowControl();
   1.921 +
   1.922 +	TUint* pE=aChar+aCount;
   1.923 +	TInt e=KErrNone;
   1.924 +	TInt i=iRxPutIndex;
   1.925 +	TInt g=iRxGetIndex;
   1.926 +	TInt s=iRxBufSize;
   1.927 +	g=g?g-1:s-1;
   1.928 +	TInt p=iRxOutstanding?-1:0;
   1.929 +    TInt thresh=iRxBufReq.iLen-iRxDesPos;
   1.930 +	while(aChar<pE)
   1.931 +		{
   1.932 +		TUint c=*aChar++;
   1.933 +
   1.934 +		// Check for parity errors and replace char if so configured.
   1.935 +		if (c & KReceiveIsrParityError)
   1.936 +			{
   1.937 +			// Replace bad character
   1.938 +			if (iConfig.iParityError==KConfigParityErrorReplaceChar)
   1.939 +				c = c & ~(0xff|KReceiveIsrParityError) | iConfig.iParityErrorChar;
   1.940 +			// Ignore parity error
   1.941 +			if (iConfig.iParityError==KConfigParityErrorIgnore)
   1.942 +				c = c & ~KReceiveIsrParityError;
   1.943 +			}
   1.944 +		
   1.945 +		if (i!=g)
   1.946 +			{
   1.947 +			iRxCharBuf[i]=(TUint8)c;
   1.948 +			iRxErrorBuf[i]=(TUint8)(c>>24);
   1.949 +
   1.950 +			if (c & KReceiveIsrMaskError)
   1.951 +				{
   1.952 +				__UART_RX_ERROR(c);
   1.953 +				if (c & KReceiveIsrOverrunError)
   1.954 +					e = KErrCommsOverrun;
   1.955 +				else if (c & KReceiveIsrBreakError)
   1.956 +					e = KErrCommsBreak;
   1.957 +				else if (c & KReceiveIsrFrameError)
   1.958 +					e = KErrCommsFrame;
   1.959 +				else if (c & KReceiveIsrParityError)
   1.960 +					e = KErrCommsParity;
   1.961 +				}
   1.962 +			count++;
   1.963 +			if (++i==s)
   1.964 +				i=0;
   1.965 +			if (p<0)
   1.966 +				{
   1.967 +				if (e || IsTerminator(TUint8(c)) || count==thresh)
   1.968 +					{
   1.969 +					// need to complete client request
   1.970 +					iRxError = e;
   1.971 +					p=i;
   1.972 +					}
   1.973 +				}
   1.974 +			}
   1.975 +		else
   1.976 +			{
   1.977 +			__OVERRUN();
   1.978 +			// buffer overrun, discard character
   1.979 +			e=KErrCommsOverrun;
   1.980 +
   1.981 +			// make sure client is informed of overrun error
   1.982 +			iRxError=e;
   1.983 +
   1.984 +			// discard remaining characters and complete
   1.985 +			p=i;
   1.986 +			break;
   1.987 +			}
   1.988 +		}
   1.989 +	iRxPutIndex=i;
   1.990 +
   1.991 +	if (iRxOutstanding)
   1.992 +		{
   1.993 +		if (p>=0)
   1.994 +			{
   1.995 +			// need to complete client request
   1.996 +			iRxBufCompleteIndex=p;
   1.997 +			iRxOutstanding=EFalse;
   1.998 +            RxComplete();
   1.999 +			}
  1.1000 +		else if (count>=iRxDrainThreshold)
  1.1001 +			{
  1.1002 +			// drain buffer but don't complete
  1.1003 +			DrainRxBuffer();
  1.1004 +			}
  1.1005 +		else if (iRxOneOrMore<0)
  1.1006 +			{
  1.1007 +			// doing read one or more - drain the buffer
  1.1008 +			// this will start the timer
  1.1009 +			iRxOneOrMore=1;
  1.1010 +			DrainRxBuffer();
  1.1011 +			}
  1.1012 +		}
  1.1013 +
  1.1014 +	__SPIN_UNLOCK_IRQRESTORE(iLock, irqstate);
  1.1015 +
  1.1016 +	if (iNotifyData)
  1.1017 +		{
  1.1018 +		iNotifyData=EFalse;
  1.1019 +        RxComplete();
  1.1020 +		}
  1.1021 +	}
  1.1022 +
  1.1023 +void DChannelComm::CheckTxBuffer()
  1.1024 +	{
  1.1025 +	// if buffer count < threshold, fill from client buffer
  1.1026 +	TInt count=TxCount();
  1.1027 +    if (iTxOutstanding && iTxDesPos<iTxBufReq.iLen && count<iTxFillThreshold)
  1.1028 +		iTxFillDfc.Add();
  1.1029 +	else if (count==0)
  1.1030 +		{
  1.1031 +		// TX buffer is now empty - see if we need to complete anything
  1.1032 +		if (iTxOutstanding)
  1.1033 +			{
  1.1034 +            if (iTxBufReq.iLen==0)
  1.1035 +				{
  1.1036 +				// request was a zero-length write - complete if hardware flow control
  1.1037 +				// is not asserted
  1.1038 +				if ((~iSignals & iHoldSignals)==0)
  1.1039 +					{
  1.1040 +					iTxOutstanding=EFalse;
  1.1041 +                    TxComplete();
  1.1042 +					}
  1.1043 +				}
  1.1044 +			else
  1.1045 +				{
  1.1046 +				// request was normal TX - complete now if not doing early completion
  1.1047 +				if (!(iConfig.iHandshake&KConfigWriteBufferedComplete))
  1.1048 +					{
  1.1049 +					iTxOutstanding=EFalse;
  1.1050 +					TxComplete();
  1.1051 +					}
  1.1052 +				}
  1.1053 +			}
  1.1054 +		}
  1.1055 +	}
  1.1056 +
  1.1057 +
  1.1058 +//
  1.1059 +// Pdd callback
  1.1060 +//
  1.1061 +void DChannelComm::UpdateSignals(TUint aSignals)
  1.1062 +	{
  1.1063 +    __KTRACE_OPT(KHARDWARE,Kern::Printf("CommSig: Upd %08x",aSignals));
  1.1064 +    iSignals=(iSignals&~KDTEInputSignals)|(aSignals&KDTEInputSignals);
  1.1065 +    DoSigNotify();	
  1.1066 +	}
  1.1067 +
  1.1068 +
  1.1069 +
  1.1070 +/**
  1.1071 + Handle a state change from the PDD. Called in ISR or DFC context.
  1.1072 + */
  1.1073 +void DChannelComm::StateIsr(TUint aSignals)
  1.1074 +    {
  1.1075 +    iSignals=(iSignals&~KDTEInputSignals)|(aSignals&KDTEInputSignals);
  1.1076 +    if (iSignalsReq->IsReady() && ((iSignals^iNotifiedSignals)&iSigNotifyMask) )
  1.1077 +        {
  1.1078 +        iSigNotifyDfc.Add();
  1.1079 +        }
  1.1080 +    if (IsLineFail(iFailSignals))
  1.1081 +        {
  1.1082 +        if (iRxOutstanding)
  1.1083 +            {
  1.1084 +            iRxError=KErrCommsLineFail;
  1.1085 +            iRxBufCompleteIndex=iRxPutIndex;
  1.1086 +            iRxOutstanding=EFalse;
  1.1087 +			RxComplete();				
  1.1088 +            }
  1.1089 +        if (iTxOutstanding)
  1.1090 +            {
  1.1091 +            iTxError = KErrCommsLineFail;
  1.1092 +            iTxOutstanding=EFalse;
  1.1093 +			TxComplete();
  1.1094 +			}
  1.1095 +        }
  1.1096 +
  1.1097 +	//
  1.1098 +	// Now we must determine if output is to be held
  1.1099 +	//
  1.1100 +    TUint status = ~iSignals & iHoldSignals;
  1.1101 +    if (iOutputHeld & KXoffSignal)
  1.1102 +        status |= KXoffSignal;      // Leave the xon/xoff handshake bit
  1.1103 +
  1.1104 +    LOG(("State - ISR - 0x%x",status));
  1.1105 +    iOutputHeld=status;             // record new flow control state
  1.1106 +    if (iTxGetIndex==iTxPutIndex)
  1.1107 +        {
  1.1108 +        // Tx buffer is empty
  1.1109 +        if (iTxOutstanding && iTxBufReq.iLen==0 && (status&~KXoffSignal)==0)
  1.1110 +            {
  1.1111 +            // if hardware flow control released, complete zero-length write
  1.1112 +            iTxOutstanding=EFalse;
  1.1113 +			TxComplete();
  1.1114 +			}
  1.1115 +        }
  1.1116 +    else if (status==0)
  1.1117 +        {
  1.1118 +        // Tx buffer not empty and flow control released, so restart transmission
  1.1119 +        LOG(("Calling LDD:EnTx"));
  1.1120 +        EnableTransmit();
  1.1121 +        }
  1.1122 +    }
  1.1123 +
  1.1124 +// check if transmitter is flow controlled
  1.1125 +void DChannelComm::CheckOutputHeld()
  1.1126 +	{
  1.1127 +	iOutputHeld=(iOutputHeld & KXoffSignal) | (~iSignals & iHoldSignals);
  1.1128 +    LOG(("CheckOPH IOH = %d",iOutputHeld));
  1.1129 +	}
  1.1130 +
  1.1131 +void DChannelComm::HandleMsg(TMessageBase* aMsg)
  1.1132 +	{
  1.1133 +
  1.1134 +	if (iStandby)
  1.1135 +		{ // postpone message handling to transition from standby
  1.1136 +		iMsgHeld=ETrue;
  1.1137 +		return;
  1.1138 +		}
  1.1139 +
  1.1140 +	TThreadMessage& m=*(TThreadMessage*)aMsg;
  1.1141 +	LOG(("HandleMsg(%x a1=%x, a2=%x)", m.iValue, m.Int1(), m.Int2()));
  1.1142 +	TInt id=m.iValue;
  1.1143 +	if (id==(TInt)ECloseMsg)
  1.1144 +		{
  1.1145 +		Shutdown();
  1.1146 +		iStatus = EClosed;
  1.1147 +		m.Complete(KErrNone, EFalse);
  1.1148 +		return;
  1.1149 +		}
  1.1150 +	else if (id==KMaxTInt)
  1.1151 +		{
  1.1152 +		// DoCancel
  1.1153 +		DoCancel(m.Int0());
  1.1154 +		m.Complete(KErrNone,ETrue);
  1.1155 +		return;
  1.1156 +		}
  1.1157 +
  1.1158 +	if (id<0)
  1.1159 +		{
  1.1160 +		// DoRequest
  1.1161 +        DoRequest(~id,m.Ptr1(),m.Ptr2());
  1.1162 +		m.Complete(KErrNone,ETrue);
  1.1163 +		}
  1.1164 +	else
  1.1165 +		{
  1.1166 +		// DoControl
  1.1167 +		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
  1.1168 +		m.Complete(r,ETrue);
  1.1169 +		}
  1.1170 +	}
  1.1171 +
  1.1172 +void DChannelComm::DoCancel(TInt aMask)
  1.1173 +//
  1.1174 +// Cancel an outstanding request.
  1.1175 +//
  1.1176 +	{
  1.1177 +	LOG(("DoCancel(%d)", aMask));
  1.1178 +	if (aMask & RBusDevComm::ERequestReadCancel)
  1.1179 +		{
  1.1180 +		TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.1181 +		iRxOutstanding=EFalse;
  1.1182 +		iNotifyData=EFalse;
  1.1183 +		iRxDesPos=0;
  1.1184 +        iRxBufReq.iLen=0;
  1.1185 +		iRxError=KErrNone;
  1.1186 +		iRxOneOrMore=0;
  1.1187 +		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1188 +		iRxCompleteDfc.Cancel();
  1.1189 +		iRxDrainDfc.Cancel();
  1.1190 +		iTimer.Cancel();
  1.1191 +		iTimerDfc.Cancel();
  1.1192 +		Complete(ERx,KErrCancel);
  1.1193 +		}
  1.1194 +	if (aMask & RBusDevComm::ERequestWriteCancel)
  1.1195 +		{
  1.1196 +		TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.1197 +        iTurnaroundTransmitDelayed = EFalse;
  1.1198 +        iTxPutIndex=0;
  1.1199 +        iTxGetIndex=0;
  1.1200 +        iTxOutstanding=EFalse;
  1.1201 +        iTxDesPos=0;
  1.1202 +        iTxBufReq.iLen=0;
  1.1203 +		iTxError=KErrNone;
  1.1204 +		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1205 +		iTxCompleteDfc.Cancel();
  1.1206 +		iTxFillDfc.Cancel();
  1.1207 +		Complete(ETx,KErrCancel);
  1.1208 +		}
  1.1209 +    if (aMask & RBusDevComm::ERequestNotifySignalChangeCancel)
  1.1210 +        {
  1.1211 +        iSigNotifyDfc.Cancel();
  1.1212 +        Complete(ESigChg,KErrCancel);
  1.1213 +        }
  1.1214 +    if (aMask & RBusDevComm::ERequestBreakCancel)
  1.1215 +		{
  1.1216 +	 	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.1217 +		if (iTurnaroundBreakDelayed)
  1.1218 +			iTurnaroundBreakDelayed=EFalse;
  1.1219 +		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1220 +
  1.1221 +		iBreakDfc.Cancel();
  1.1222 +		iBreakTimer.Cancel();
  1.1223 +		FinishBreakImplementation(KErrCancel);
  1.1224 +		}
  1.1225 +	}
  1.1226 +
  1.1227 +/**
  1.1228 + Intercept messages in client context before they are sent to the DFC queue
  1.1229 + */
  1.1230 +TInt DChannelComm::SendMsg(TMessageBase* aMsg)
  1.1231 +	{
  1.1232 +	TInt r = KErrNone;
  1.1233 +	TInt max;
  1.1234 +	TInt len = 0;
  1.1235 +	TThreadMessage* m = (TThreadMessage*)aMsg;
  1.1236 +
  1.1237 +	// Handle ECloseMsg & Cancel
  1.1238 +    TInt id=aMsg->iValue;
  1.1239 +    if (id==(TInt)ECloseMsg || id==KMaxTInt)
  1.1240 +        {
  1.1241 +		LOG(("SendMsg(%s)", (id==KMaxTInt)?"Cancel":"ECloseMsg"));
  1.1242 +		// do nothing cos these are handled on the DFC side
  1.1243 +        }
  1.1244 +	
  1.1245 +	// Handle control messages that access user memory here in client context
  1.1246 +    else if (id >= 0) 
  1.1247 +		{
  1.1248 +		TAny* a1 = m->iArg[0];
  1.1249 +		switch (aMsg->iValue) 
  1.1250 +			{
  1.1251 +			case RBusDevComm::EControlConfig:
  1.1252 +				{			
  1.1253 +				LOG(("SendMsg(EControlConfig, %x)", a1));
  1.1254 +				TPtrC8 cfg((const TUint8*)&iConfig,sizeof(iConfig));
  1.1255 +				return Kern::ThreadDesWrite(iClient,a1,cfg,0,KTruncateToMaxLength,iClient);
  1.1256 +				}
  1.1257 +			case RBusDevComm::EControlSetConfig:
  1.1258 +				{
  1.1259 +				LOG(("SendMsg(EControlSetConfig, %x)", a1));
  1.1260 +				if (AreAnyPending()) 
  1.1261 +					; // r = ESetConfigWhileRequestPending;
  1.1262 +				else
  1.1263 +					r = Kern::PinVirtualMemory(iPinObjSetConfig, (TLinAddr)a1, sizeof(TCommConfigV01));
  1.1264 +				}
  1.1265 +				break;
  1.1266 +			case RBusDevComm::EControlCaps:
  1.1267 +				{
  1.1268 +				LOG(("SendMsg(EControlCaps, %x)", a1));
  1.1269 +				TCommCaps2 caps;
  1.1270 +				PddCaps(caps);
  1.1271 +				return Kern::ThreadDesWrite(iClient,a1,caps,0,KTruncateToMaxLength,iClient);
  1.1272 +				}
  1.1273 +			default:
  1.1274 +				// Allow other control messages to go to DFC thread
  1.1275 +				LOG(("SendMsg(Ctrl %d, %x)", aMsg->iValue, a1));
  1.1276 +				break;
  1.1277 +			}
  1.1278 +		}
  1.1279 +
  1.1280 +
  1.1281 +	// Handle requests
  1.1282 +	else 
  1.1283 +		{
  1.1284 +		TRequestStatus* status = (TRequestStatus*)m->iArg[0];
  1.1285 +		TAny* a1 = m->iArg[1];
  1.1286 +		TAny* a2 = m->iArg[2];
  1.1287 +		TInt reqNo = ~aMsg->iValue;
  1.1288 +		TInt irq;
  1.1289 +		switch (reqNo)
  1.1290 +			{
  1.1291 +			case RBusDevComm::ERequestRead:
  1.1292 +				{
  1.1293 +			    iNotifyData=EFalse;
  1.1294 +				// If client has *not* provided a buffer pointer, it means they only want
  1.1295 +				// to know when data becomes available.
  1.1296 +				if (!a1)
  1.1297 +					{
  1.1298 +					irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.1299 +					TBool isEmpty = (iRxPutIndex==iRxGetIndex);
  1.1300 +					iNotifyData = isEmpty;
  1.1301 +					__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1302 +					if (!isEmpty) // if Rx buffer has bytes in it we can complete the request immediately
  1.1303 +						{
  1.1304 +						Kern::RequestComplete(status, KErrNone);
  1.1305 +						return KErrNone;
  1.1306 +						}
  1.1307 +					// Do not start the Turnaround timer as this is not a Read request but a request for Data Available notification
  1.1308 +					LOG(("--Buf Empty--"));
  1.1309 +					}
  1.1310 +
  1.1311 +				// Get buffer length if one has been given
  1.1312 +				if (a2)
  1.1313 +					r = Kern::ThreadRawRead(iClient,a2,&len,sizeof(len)); 
  1.1314 +
  1.1315 +				// Check the client descriptor is valid and large enough to hold the required amount of data.
  1.1316 +				if (a1 && r==KErrNone) 
  1.1317 +					{
  1.1318 +					max = Kern::ThreadGetDesMaxLength(iClient, a1);
  1.1319 +					if (max<Abs(len) || max<0)
  1.1320 +						r = KErrGeneral; // do not start the Turnaround timer (invalid Descriptor this read never starts)
  1.1321 +					}
  1.1322 +
  1.1323 +				LOG(("SendMsg(ERequestRead, %x, len=%d) max=%d r=%d", a1, len, max, r));
  1.1324 +
  1.1325 +				// Set client descriptor length to zero & set up client buffer object
  1.1326 +				if (a1 && r==KErrNone) 
  1.1327 +					{
  1.1328 +					TPtrC8 p(NULL,0);
  1.1329 +					r = Kern::ThreadDesWrite(iClient,a1,p,0,0,iClient);
  1.1330 +					if (r == KErrNone)
  1.1331 +						r = iRxBufReq.Setup(status, a1, len);
  1.1332 +					}
  1.1333 +				}
  1.1334 +			break;
  1.1335 +
  1.1336 +
  1.1337 +			//
  1.1338 +			// ERequestWrite
  1.1339 +			//
  1.1340 +			case RBusDevComm::ERequestWrite:
  1.1341 +				if (iStatus==EClosed)
  1.1342 +					r = KErrNotReady;
  1.1343 +				else if (!a1) 
  1.1344 +					r = KErrArgument;
  1.1345 +				else 
  1.1346 +					r=Kern::ThreadRawRead(iClient, a2, &len, sizeof(len));
  1.1347 +				LOG(("SendMsg(ERequestWrite, %x, len=%d) r=%d", a1, len, r));
  1.1348 +
  1.1349 +				// Setup pending client request for this write
  1.1350 +				if (r==KErrNone)
  1.1351 +					r = iTxBufReq.Setup(status, a1, len);		
  1.1352 +				break;
  1.1353 +
  1.1354 +
  1.1355 +			//
  1.1356 +			// ERequestBreak: a1 points to the number of microseconds to break for
  1.1357 +			//
  1.1358 +			case RBusDevComm::ERequestBreak:
  1.1359 +				r = Kern::ThreadRawRead(iClient, a1, &iBreakTimeMicroSeconds, sizeof(TInt));
  1.1360 +				if (r == KErrNone)
  1.1361 +					r = iBreakStatus->SetStatus(status);					
  1.1362 +				LOG(("SendMsg(ERequestBreak, %x) bktime=%d r=%d", a1, iBreakTimeMicroSeconds, r));
  1.1363 +				break;
  1.1364 +
  1.1365 +
  1.1366 +			//
  1.1367 +			// ERequestNotifySignalChange:	a1 points to user-side int to receive the signals bitmask
  1.1368 +			//								a2 points to the bitmask of signals the user is interested in
  1.1369 +			//
  1.1370 +			case RBusDevComm::ERequestNotifySignalChange:
  1.1371 +				LOG(("SendMsg(ERequestNotifySignalChange, %x, %x)", a1, a2));
  1.1372 +				if (!a1 || !a2)
  1.1373 +					{
  1.1374 +					r = KErrArgument;
  1.1375 +					break;
  1.1376 +					}
  1.1377 +				// Setup word-sized client buffer
  1.1378 +				r = Kern::ThreadRawRead(iClient,a2,&iSigNotifyMask,sizeof(TUint));
  1.1379 +				irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.1380 +				if (r==KErrNone) 
  1.1381 +					{
  1.1382 +					r = iSignalsReq->SetStatus(status);
  1.1383 +					if (r==KErrNone) 
  1.1384 +						iSignalsReq->SetDestPtr(a1);
  1.1385 +					}
  1.1386 +				LOG(("ERequestNotifySignalChange: mask is %x, r is %d", iSigNotifyMask, r));
  1.1387 +				__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1388 +				break;
  1.1389 +
  1.1390 +
  1.1391 +			// Unknown request
  1.1392 +			default:
  1.1393 +				LOG(("SendMsg(req %d, %x, %x)", reqNo, a1, a2));
  1.1394 +				r = KErrNotSupported;
  1.1395 +				break;
  1.1396 +
  1.1397 +			}
  1.1398 +
  1.1399 +			// If the request has an error, complete immediately
  1.1400 +			if (r!=KErrNone)
  1.1401 +				Kern::RequestComplete(status, r);
  1.1402 +		}
  1.1403 +
  1.1404 +	// Send the client request to the DFC queue unless there's been an error
  1.1405 +	if (r==KErrNone)
  1.1406 +		r = DLogicalChannel::SendMsg(aMsg);
  1.1407 +	LOG(("<SendMsg ret %d", r));
  1.1408 +	return r;
  1.1409 +
  1.1410 +	}
  1.1411 +
  1.1412 +
  1.1413 +/**
  1.1414 + Handle asynchronous requests. Called in DFC context.
  1.1415 + */
  1.1416 +void DChannelComm::DoRequest(TInt aReqNo, TAny* a1, TAny* a2)
  1.1417 +    {
  1.1418 +	LOG(("DoRequest(%d %x %x)", aReqNo, a1, a2));
  1.1419 +
  1.1420 +    //
  1.1421 +    // First check if we have started
  1.1422 +    //
  1.1423 +    if (iStatus==EOpen)
  1.1424 +        {
  1.1425 +        Start();
  1.1426 +        CheckOutputHeld();
  1.1427 +        SetSignals(iAutoSignals,0);
  1.1428 +        LOG(("DReq- RFC"));
  1.1429 +        ReleaseFlowControl();
  1.1430 +        }
  1.1431 +    //
  1.1432 +    // Check for a line fail
  1.1433 +    //
  1.1434 +    if (IsLineFail(iFailSignals))
  1.1435 +		{
  1.1436 +		Complete(EAll, KErrCommsLineFail);
  1.1437 +		return;
  1.1438 +		}	
  1.1439 +
  1.1440 +    //
  1.1441 +    // Now we can dispatch the async request
  1.1442 +    //
  1.1443 +    switch (aReqNo)
  1.1444 +        {
  1.1445 +        case RBusDevComm::ERequestRead:
  1.1446 +			InitiateRead(iRxBufReq.iLen);
  1.1447 +            break;
  1.1448 +
  1.1449 +        case RBusDevComm::ERequestWrite:
  1.1450 +            {
  1.1451 +			
  1.1452 +			// See if we need to delay the write
  1.1453 +            TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.1454 +			iTurnaroundTransmitDelayed = iTurnaroundTimerRunning!=0;
  1.1455 +			iBreakDelayedTx = (iFlags & KBreaking);
  1.1456 +			__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1457 +
  1.1458 +			// If we do need to delay the write
  1.1459 +            if (iTurnaroundTransmitDelayed || iBreakDelayedTx)
  1.1460 +                break;
  1.1461 +			
  1.1462 +			//
  1.1463 +			InitiateWrite();
  1.1464 +            break;
  1.1465 +            }
  1.1466 +
  1.1467 +        case RBusDevComm::ERequestNotifySignalChange:
  1.1468 +            iNotifiedSignals = iSignals;
  1.1469 +			DoSigNotify();
  1.1470 +            break;
  1.1471 +            
  1.1472 +        case RBusDevComm::ERequestBreak:
  1.1473 +			if(iTurnaroundTimerRunning)
  1.1474 +				iTurnaroundBreakDelayed = ETrue;
  1.1475 +			else
  1.1476 +				BreakOn();
  1.1477 +			break;
  1.1478 +
  1.1479 +        }
  1.1480 +    }
  1.1481 +
  1.1482 +/**
  1.1483 + Called in DFC context upon receipt of ERequestRead
  1.1484 + */
  1.1485 +void DChannelComm::InitiateRead(TInt aLength)
  1.1486 +    {
  1.1487 +    LOG(("InitiateRead(%d)", aLength));
  1.1488 +    iRxOutstanding=EFalse;
  1.1489 +	iRxOneOrMore=0;
  1.1490 +
  1.1491 +    // Complete zero-length read immediately
  1.1492 +    if (aLength==0)
  1.1493 +        {
  1.1494 +		iRxBufReq.Complete(iClient, KErrNone);
  1.1495 +        RestartTurnaroundTimer();
  1.1496 +        return;
  1.1497 +        }
  1.1498 +
  1.1499 +	TBool length_negative = (aLength<0);
  1.1500 +	if (length_negative)
  1.1501 +		aLength = -aLength;
  1.1502 +	iRxBufReq.iLen=aLength;
  1.1503 +
  1.1504 +    // If the RX buffer is empty, we must wait for more data
  1.1505 +    TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.1506 +    if (iRxPutIndex==iRxGetIndex)
  1.1507 +        {
  1.1508 +		if (length_negative)
  1.1509 +            iRxOneOrMore=-1;        // -1 because timer not started
  1.1510 +        iRxOutstanding=ETrue;
  1.1511 +        __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1512 +        return;
  1.1513 +        }
  1.1514 +    __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1515 +
  1.1516 +    // RX buffer contains characters, must scan buffer and then complete
  1.1517 +	if (length_negative)
  1.1518 +        {
  1.1519 +        // ReceiveOneOrMore, up to -aLength characters
  1.1520 +        iRxOneOrMore=1;
  1.1521 +        }
  1.1522 +    TInt getIndex=iRxGetIndex;
  1.1523 +    TInt count=0;
  1.1524 +    TUint stat=0;
  1.1525 +	TBool complete=EFalse;
  1.1526 +    while(!complete)
  1.1527 +        {
  1.1528 +        while(count<aLength && getIndex!=iRxPutIndex)
  1.1529 +            {
  1.1530 +            if ((stat=iRxErrorBuf[getIndex])!=0 || IsTerminator(iRxCharBuf[getIndex]))
  1.1531 +                {
  1.1532 +                // this character will complete the request
  1.1533 +                if (++getIndex==iRxBufSize)
  1.1534 +                    getIndex=0;
  1.1535 +                count++;
  1.1536 +                complete=ETrue;
  1.1537 +                break;
  1.1538 +                }
  1.1539 +            if (++getIndex==iRxBufSize)
  1.1540 +                getIndex=0;
  1.1541 +            count++;
  1.1542 +            }
  1.1543 +        if (count==aLength)
  1.1544 +            complete=ETrue;
  1.1545 +        if (!complete)
  1.1546 +            {
  1.1547 +            TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.1548 +            if (getIndex==iRxPutIndex)
  1.1549 +                {
  1.1550 +                // not enough chars to complete request, so set up to wait for more
  1.1551 +                iRxOutstanding=ETrue;
  1.1552 +                __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1553 +                if (count)
  1.1554 +                    DoDrainRxBuffer(getIndex);
  1.1555 +                return;
  1.1556 +                }
  1.1557 +            // more characters have arrived, loop again
  1.1558 +            __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1559 +            }
  1.1560 +        }
  1.1561 +
  1.1562 +    // can complete request right now
  1.1563 +    TInt e=KErrNone;
  1.1564 +    if (stat)
  1.1565 +        {
  1.1566 +        stat<<=24;
  1.1567 +        if (stat & KReceiveIsrOverrunError)
  1.1568 +            e = KErrCommsOverrun;
  1.1569 +        else if (stat & KReceiveIsrBreakError)
  1.1570 +	        e = KErrCommsBreak;
  1.1571 +        else if (stat & KReceiveIsrFrameError)
  1.1572 +            e = KErrCommsFrame;
  1.1573 +        else if (stat & KReceiveIsrParityError)
  1.1574 +            e = KErrCommsParity;
  1.1575 +        }
  1.1576 +    if (iRxError==KErrNone)
  1.1577 +        iRxError=e;
  1.1578 +    iRxBufCompleteIndex=getIndex;
  1.1579 +    DoCompleteRx();
  1.1580 +    }
  1.1581 +
  1.1582 +/**
  1.1583 + Called in DFC context to start a write or a delayed write
  1.1584 + */
  1.1585 +void DChannelComm::InitiateWrite()
  1.1586 +    {
  1.1587 +    LOG(("InitiateWrite() len=%d", iTxBufReq.iLen));
  1.1588 +
  1.1589 +
  1.1590 +	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.1591 +	iTxDesPos=0;
  1.1592 +	iTurnaroundTimerStartTime = 0;
  1.1593 +	iTurnaroundTimerStartTimeValid = 2;
  1.1594 +	if (~iSignals & iFailSignals)
  1.1595 +		{
  1.1596 +		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1597 +		iTxBufReq.Complete(iClient, KErrCommsLineFail);
  1.1598 +		return;
  1.1599 +		}
  1.1600 +	if (iTxBufReq.iLen==0)
  1.1601 +		{
  1.1602 +		if (iTxPutIndex==iTxGetIndex && (~iSignals & iHoldSignals)==0)
  1.1603 +			{
  1.1604 +			__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1605 +			iTxBufReq.Complete(iClient, KErrNone);
  1.1606 +			return;
  1.1607 +			}
  1.1608 +		}
  1.1609 +
  1.1610 +	iTxOutstanding=ETrue;
  1.1611 +	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1612 +	if (iTxBufReq.iLen!=0)
  1.1613 +		DoFillTxBuffer();
  1.1614 +	}
  1.1615 +
  1.1616 +void DChannelComm::SigNotifyDfc(TAny* aPtr)
  1.1617 +	{
  1.1618 +	((DChannelComm*)aPtr)->DoSigNotify();
  1.1619 +	}
  1.1620 +
  1.1621 +void DChannelComm::DoSigNotify()
  1.1622 +    {
  1.1623 +	// Atomically update iNotifiedSignals and prepare to signal
  1.1624 +	TBool do_notify = EFalse;
  1.1625 +    TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.1626 +    TUint orig_sig=iNotifiedSignals;
  1.1627 +    if (iSignalsReq->IsReady() && ( iNotifiedSignals==0xffffffff || ((iSignals^iNotifiedSignals)&iSigNotifyMask) ) )
  1.1628 +        {
  1.1629 +        iNotifiedSignals=iSignals;
  1.1630 +        do_notify=ETrue;
  1.1631 +        }
  1.1632 +    __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1633 +    __KTRACE_OPT(KHARDWARE,Kern::Printf("CommSig: Orig=%08x New %08x Mask %08x",orig_sig,iNotifiedSignals,iSigNotifyMask));
  1.1634 +    if (do_notify)
  1.1635 +        {
  1.1636 +        TUint changed=iSigNotifyMask;
  1.1637 +        if (orig_sig!=0xffffffff)
  1.1638 +            changed&=(orig_sig^iNotifiedSignals);
  1.1639 +        changed=(changed<<12)|(iNotifiedSignals&iSigNotifyMask);
  1.1640 +
  1.1641 +		// Write the result back to client memory and complete the request
  1.1642 +		__KTRACE_OPT(KHARDWARE,Kern::Printf("CommSig: Notify %08x",changed));
  1.1643 +		LOG(("DoSigNotify: %08x",changed));
  1.1644 +		TUint& rr = iSignalsReq->Data();
  1.1645 +		rr = changed;
  1.1646 +		Kern::QueueRequestComplete(iClient, iSignalsReq, KErrNone);
  1.1647 +		}
  1.1648 +    }
  1.1649 +
  1.1650 +
  1.1651 +/**
  1.1652 + Manually read and act on signals
  1.1653 + */
  1.1654 +void DChannelComm::UpdateAndProcessSignals()
  1.1655 +    {
  1.1656 +    TUint signals=Signals();
  1.1657 +    TBool notify=EFalse;
  1.1658 +    TBool complete_rx=EFalse;
  1.1659 +    TBool complete_tx=EFalse;
  1.1660 +    TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.1661 +    iSignals=(iSignals&~KDTEInputSignals)|(signals&KDTEInputSignals);
  1.1662 +    if (iSignalsReq->IsReady() && ((iSignals^iNotifiedSignals)&iSigNotifyMask) )
  1.1663 +        {
  1.1664 +        notify=ETrue;
  1.1665 +        }
  1.1666 +    if (IsLineFail(iFailSignals))
  1.1667 +        {
  1.1668 +        if (iRxOutstanding)
  1.1669 +            {
  1.1670 +            iRxError=KErrCommsLineFail;
  1.1671 +            iRxBufCompleteIndex=iRxPutIndex;
  1.1672 +            iRxOutstanding=EFalse;
  1.1673 +            complete_rx=ETrue;
  1.1674 +            }
  1.1675 +        if (iTxOutstanding)
  1.1676 +            {
  1.1677 +            iTxError = KErrCommsLineFail;
  1.1678 +            iTxOutstanding=EFalse;
  1.1679 +            complete_tx=ETrue;
  1.1680 +            }
  1.1681 +        }
  1.1682 +    //
  1.1683 +    // Now we must determine if output is to be held
  1.1684 +    //
  1.1685 +    TUint status = ~iSignals & iHoldSignals;
  1.1686 +    if (iOutputHeld & KXoffSignal)
  1.1687 +        status |= KXoffSignal;      // Leave the xon/xoff handshake bit
  1.1688 +
  1.1689 +    iOutputHeld=status;             // record new flow control state
  1.1690 +    if (iTxGetIndex==iTxPutIndex)
  1.1691 +        {
  1.1692 +        // Tx buffer is empty
  1.1693 +        if (iTxOutstanding && iTxBufReq.iLen==0 && (status&~KXoffSignal)==0)
  1.1694 +            {
  1.1695 +            // if hardware flow control released, complete zero-length write
  1.1696 +            iTxOutstanding=EFalse;
  1.1697 +            complete_tx=ETrue;
  1.1698 +            }
  1.1699 +        }
  1.1700 +    else if (status==0)
  1.1701 +        {
  1.1702 +        // Tx buffer not empty and flow control released, so restart transmission
  1.1703 +        EnableTransmit();
  1.1704 +        }
  1.1705 +    __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1706 +    if (notify)
  1.1707 +        DoSigNotify();
  1.1708 +    if (complete_rx)
  1.1709 +        DoCompleteRx();
  1.1710 +    if (complete_tx)
  1.1711 +        DoCompleteTx();
  1.1712 +    }
  1.1713 +
  1.1714 +
  1.1715 +TUint DChannelComm::FailSignals(TUint aHandshake)
  1.1716 +	{
  1.1717 +	TUint r=0;
  1.1718 +	if ((aHandshake&(KConfigObeyCTS|KConfigFailCTS))==(KConfigObeyCTS|KConfigFailCTS))
  1.1719 +		r|=KSignalCTS;
  1.1720 +	if ((aHandshake&(KConfigObeyDSR|KConfigFailDSR))==(KConfigObeyDSR|KConfigFailDSR))
  1.1721 +		r|=KSignalDSR;
  1.1722 +	if ((aHandshake&(KConfigObeyDCD|KConfigFailDCD))==(KConfigObeyDCD|KConfigFailDCD))
  1.1723 +		r|=KSignalDCD;
  1.1724 +	return r;
  1.1725 +	}
  1.1726 +
  1.1727 +TUint DChannelComm::HoldSignals(TUint aHandshake)
  1.1728 +	{
  1.1729 +	TUint r=0;
  1.1730 +	if (aHandshake & KConfigObeyCTS)
  1.1731 +		r|=KSignalCTS;
  1.1732 +	if (aHandshake & KConfigObeyDSR)
  1.1733 +		r|=KSignalDSR;
  1.1734 +	if (aHandshake & KConfigObeyDCD)
  1.1735 +		r|=KSignalDCD;
  1.1736 +	return r;
  1.1737 +	}
  1.1738 +
  1.1739 +TUint DChannelComm::FlowControlSignals(TUint aHandshake)
  1.1740 +	{
  1.1741 +	TUint r=0;
  1.1742 +	if (!(aHandshake & KConfigFreeRTS))
  1.1743 +		r|=KSignalRTS;
  1.1744 +	else if (!(aHandshake & KConfigFreeDTR))
  1.1745 +		r|=KSignalDTR;
  1.1746 +	return r;
  1.1747 +	}
  1.1748 +
  1.1749 +TUint DChannelComm::AutoSignals(TUint aHandshake)
  1.1750 +	{
  1.1751 +	TUint r=0;
  1.1752 +	if (!(aHandshake & KConfigFreeRTS) && !(aHandshake & KConfigFreeDTR))
  1.1753 +		r|=KSignalDTR;
  1.1754 +	return r;
  1.1755 +	}
  1.1756 +
  1.1757 +TInt DChannelComm::SetConfig(TCommConfigV01& c)
  1.1758 +	{
  1.1759 +	LOG(("SetConfig(...)"));
  1.1760 +	TBool restart = EFalse;
  1.1761 +	TBool purge = EFalse;
  1.1762 +	TBool changeTerminators=EFalse;
  1.1763 +	TInt irq;
  1.1764 +	TInt r;
  1.1765 +
  1.1766 +	if(c.iTerminatorCount>KConfigMaxTerminators)
  1.1767 +		return KErrNotSupported;
  1.1768 +	if ((r=ValidateConfig(c))!=KErrNone)
  1.1769 +		return r;
  1.1770 +	TUint failSignals=FailSignals(c.iHandshake);
  1.1771 +	if (IsLineFail(failSignals))
  1.1772 +		return KErrCommsLineFail;
  1.1773 +	if (iConfig.iRate != c.iRate
  1.1774 +		|| iConfig.iDataBits != c.iDataBits
  1.1775 +		|| iConfig.iStopBits != c.iStopBits
  1.1776 +		|| iConfig.iParity != c.iParity
  1.1777 +		|| iConfig.iFifo != c.iFifo
  1.1778 +		|| iConfig.iSpecialRate != c.iSpecialRate
  1.1779 +		|| iConfig.iSIREnable != c.iSIREnable
  1.1780 +		|| iConfig.iSIRSettings != c.iSIRSettings)
  1.1781 +		{
  1.1782 +		restart = ETrue;
  1.1783 +		}
  1.1784 +	else if (iConfig.iParityErrorChar != c.iParityErrorChar
  1.1785 +		|| iConfig.iParityError != c.iParityError
  1.1786 +		|| iConfig.iXonChar != c.iXonChar
  1.1787 +		|| iConfig.iXoffChar != c.iXoffChar
  1.1788 +		|| (iConfig.iHandshake&(KConfigObeyXoff|KConfigSendXoff))
  1.1789 +			!= (c.iHandshake&(KConfigObeyXoff|KConfigSendXoff)))
  1.1790 +		{
  1.1791 +		purge = ETrue;
  1.1792 +		}
  1.1793 +	else
  1.1794 +		{
  1.1795 +		if (iConfig.iTerminatorCount==c.iTerminatorCount)
  1.1796 +			{
  1.1797 +			for (TInt i=0; i<iConfig.iTerminatorCount; i++)
  1.1798 +				{
  1.1799 +				if (iConfig.iTerminator[i]!=c.iTerminator[i])
  1.1800 +					{
  1.1801 +					changeTerminators=ETrue;
  1.1802 +					break;
  1.1803 +					}
  1.1804 +				}
  1.1805 +			}
  1.1806 +		else
  1.1807 +			changeTerminators=ETrue;
  1.1808 +		if (!changeTerminators && c.iHandshake == iConfig.iHandshake)
  1.1809 +			return r;	// nothing to do.
  1.1810 +		}
  1.1811 +	if (iStatus==EActive && (restart || purge))
  1.1812 +		{
  1.1813 +		SetSignals(0,iFlowControlSignals|iAutoSignals); // Drop RTS
  1.1814 +		Stop(EStopNormal);
  1.1815 +		iStatus=EOpen;
  1.1816 +		if(purge)
  1.1817 +			ResetBuffers(ETrue);
  1.1818 +		iConfig=c;
  1.1819 +		iFailSignals=failSignals;
  1.1820 +		iHoldSignals=HoldSignals(c.iHandshake);
  1.1821 +		iFlowControlSignals=FlowControlSignals(c.iHandshake);
  1.1822 +		iAutoSignals=AutoSignals(c.iHandshake);
  1.1823 +		Start();
  1.1824 +		CheckOutputHeld();
  1.1825 +		SetSignals(iFlowControlSignals|iAutoSignals,0); // Assert RTS
  1.1826 +		irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.1827 +		}
  1.1828 +	else
  1.1829 +		{
  1.1830 +		irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.1831 +		if(purge)
  1.1832 +			ResetBuffers(ETrue);
  1.1833 +		iConfig=c;
  1.1834 +		iFailSignals=failSignals;
  1.1835 +		iHoldSignals=HoldSignals(c.iHandshake);
  1.1836 +		iFlowControlSignals=FlowControlSignals(c.iHandshake);
  1.1837 +		iAutoSignals=AutoSignals(c.iHandshake);
  1.1838 +		}
  1.1839 +	if (iConfig.iHandshake&KConfigObeyXoff)
  1.1840 +		{
  1.1841 +		iRxXonChar=c.iXonChar;
  1.1842 +		iRxXoffChar=c.iXoffChar;
  1.1843 +		}
  1.1844 +	else
  1.1845 +		{
  1.1846 +		iRxXonChar=0xffffffff;
  1.1847 +		iRxXoffChar=0xffffffff;
  1.1848 +		iOutputHeld&=~KXoffSignal;
  1.1849 +		}
  1.1850 +	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.1851 +	if (iStatus==EActive)
  1.1852 +		ReleaseFlowControl();
  1.1853 +
  1.1854 +	// no request pending here, so no need to protect this against interrupts
  1.1855 +	if (restart || purge || changeTerminators)
  1.1856 +		{
  1.1857 +		memclr(iTerminatorMask, 32);
  1.1858 +		TInt i;
  1.1859 +		for (i=0; i<iConfig.iTerminatorCount; i++)
  1.1860 +			{
  1.1861 +			SetTerminator(iConfig.iTerminator[i]);
  1.1862 +			}
  1.1863 +		}
  1.1864 +	return r;
  1.1865 +	}
  1.1866 +
  1.1867 +TInt DChannelComm::DoControl(TInt aFunction, TAny* a1, TAny* a2)
  1.1868 +//
  1.1869 +// Sync requests.
  1.1870 +//
  1.1871 +	{
  1.1872 +	LOG(("DoControl(aFunction=%d, a1=%x, a2=%x)", aFunction, a1, a2));
  1.1873 +
  1.1874 +	TInt r=KErrNone;
  1.1875 +
  1.1876 +	switch (aFunction)
  1.1877 +		{
  1.1878 +		case RBusDevComm::EControlSetConfig:
  1.1879 +			{
  1.1880 +			TCommConfigV01 c;
  1.1881 +			memclr(&c, sizeof(c));
  1.1882 +			TPtr8 cfg((TUint8*)&c,0,sizeof(c));
  1.1883 +			r=Kern::ThreadDesRead(iClient,a1,cfg,0,0);
  1.1884 +			if (r==KErrNone)
  1.1885 +				r=SetConfig(c);
  1.1886 +			}
  1.1887 +			Kern::UnpinVirtualMemory(iPinObjSetConfig);
  1.1888 +			break;
  1.1889 +
  1.1890 +		case RBusDevComm::EControlSignals:
  1.1891 +			{
  1.1892 +			UpdateAndProcessSignals();
  1.1893 +			r=iSignals;
  1.1894 +			break;
  1.1895 +			}
  1.1896 +		case RBusDevComm::EControlSetSignals:
  1.1897 +			{
  1.1898 +			TUint set=(TUint)a1;
  1.1899 +			TUint clear=(TUint)a2;
  1.1900 +			if (set & clear)
  1.1901 +;//				Kern::PanicCurrentThread(_L("D32COMM"), ESetSignalsSetAndClear);
  1.1902 +			else
  1.1903 +				{
  1.1904 +				if (iStatus==EOpen)
  1.1905 +					{
  1.1906 +					Start();
  1.1907 +					if (!(iConfig.iHandshake & KConfigFreeDTR) && !(clear & KSignalDTR))
  1.1908 +						set|=KSignalDTR; // Assert DTR
  1.1909 +					if (!(iConfig.iHandshake & KConfigFreeRTS) && !(clear & KSignalRTS))
  1.1910 +						set|=KSignalRTS; // Assert RTS
  1.1911 +					if (iConfig.iHandshake & KConfigSendXoff)
  1.1912 +						iJamChar=iConfig.iXonChar;
  1.1913 +					iInputHeld = EFalse;
  1.1914 +					CheckOutputHeld();
  1.1915 +					}
  1.1916 +				__e32_atomic_axo_ord32(&iSignals, ~(clear|set), set);
  1.1917 +				SetSignals(set,clear);
  1.1918 +				}
  1.1919 +			break;
  1.1920 +			}
  1.1921 +		case RBusDevComm::EControlQueryReceiveBuffer:
  1.1922 +			r=RxCount();
  1.1923 +			break;
  1.1924 +		case RBusDevComm::EControlResetBuffers:
  1.1925 +			if (AreAnyPending())
  1.1926 +;//				Kern::PanicCurrentThread(_L("D32COMM"), EResetBuffers);
  1.1927 +			else
  1.1928 +				ResetBuffers(ETrue);
  1.1929 +			break;
  1.1930 +		case RBusDevComm::EControlReceiveBufferLength:
  1.1931 +			r=iRxBufSize;
  1.1932 +			break;
  1.1933 +
  1.1934 +		case RBusDevComm::EControlSetReceiveBufferLength:
  1.1935 +			if (AreAnyPending())
  1.1936 +;//				iThread->Panic(_L("D32COMM"),ESetReceiveBufferLength);
  1.1937 +			else
  1.1938 +				r=SetRxBufferSize((TInt)a1);
  1.1939 +			break;
  1.1940 +		// ***************************************
  1.1941 +
  1.1942 +		case RBusDevComm::EControlMinTurnaroundTime:
  1.1943 +			r = iTurnaroundMicroSeconds;			// used saved value
  1.1944 +			break;
  1.1945 +
  1.1946 +		case RBusDevComm::EControlSetMinTurnaroundTime:
  1.1947 +				{
  1.1948 +				if (a1<0)
  1.1949 +					a1=(TAny*)0;
  1.1950 +				iTurnaroundMicroSeconds = (TUint)a1;			// save this
  1.1951 +				TUint newTurnaroundMilliSeconds = (TUint)a1/1000;	// convert to ms
  1.1952 +				if(newTurnaroundMilliSeconds != iTurnaroundMinMilliSeconds)
  1.1953 +					{
  1.1954 +                    // POLICY: if a new turnaround time is set before the previous running timer has expired 
  1.1955 + 					// then the timer is adjusted depending on the new value and if any
  1.1956 +                    // write request has been queued, transmission will proceed after the timer has expired.
  1.1957 +					if(iTurnaroundTimerStartTimeValid == 0)
  1.1958 +						{	
  1.1959 +						 iTurnaroundTimerStartTimeValid = 1;
  1.1960 +						 iTurnaroundTimerStartTime = NKern::TickCount();
  1.1961 +						}
  1.1962 +				    if(iTurnaroundTimerStartTimeValid != 2)
  1.1963 +						TurnaroundClear();
  1.1964 +					if(newTurnaroundMilliSeconds > 0)
  1.1965 +						{
  1.1966 +						r = TurnaroundSet(newTurnaroundMilliSeconds);
  1.1967 +						}
  1.1968 +					}
  1.1969 +				}
  1.1970 +			break;
  1.1971 +		default:
  1.1972 +			r=KErrNotSupported;
  1.1973 +			}
  1.1974 +		return(r);
  1.1975 +		}
  1.1976 +
  1.1977 +void DChannelComm::DoPowerUp()
  1.1978 +//
  1.1979 +// Called at switch on and upon Opening.
  1.1980 +//
  1.1981 +    {
  1.1982 +	LOG(("DoPowerUp()"));
  1.1983 +	__KTRACE_OPT(KPOWER,Kern::Printf("DChannelComm::DoPowerUp()"));
  1.1984 +
  1.1985 +	ResetBuffers(ETrue);
  1.1986 +	iRxOutstanding=EFalse;
  1.1987 +	iNotifyData=EFalse;
  1.1988 +	iTxOutstanding=EFalse;
  1.1989 +    iTxDesPos=0;
  1.1990 +    iFlags=0;
  1.1991 +
  1.1992 +	// Cancel turnaround
  1.1993 +	iTurnaroundMinMilliSeconds = 0;
  1.1994 +	iTurnaroundTimerRunning = EFalse;
  1.1995 +	iTurnaroundTransmitDelayed = EFalse;
  1.1996 +
  1.1997 +	// cancel any DFCs/timers
  1.1998 +	iRxDrainDfc.Cancel();
  1.1999 +	iRxCompleteDfc.Cancel();
  1.2000 +	iTxFillDfc.Cancel();
  1.2001 +	iTxCompleteDfc.Cancel();
  1.2002 +	iTimer.Cancel();
  1.2003 +	iTurnaroundTimer.Cancel();
  1.2004 +	iTurnaroundDfc.Cancel();
  1.2005 +	iTimerDfc.Cancel();
  1.2006 +	iSigNotifyDfc.Cancel();
  1.2007 +
  1.2008 +	Complete(EAll, KErrAbort);
  1.2009 +	if (!Kern::PowerGood())
  1.2010 +		return;
  1.2011 +	TUint hand=iConfig.iHandshake;
  1.2012 +	if (hand&(KConfigFreeRTS|KConfigFreeDTR))
  1.2013 +		{
  1.2014 +		Start();
  1.2015 +		if (!Kern::PowerGood())
  1.2016 +			return;
  1.2017 +		if (hand&KConfigFreeRTS)
  1.2018 +			{
  1.2019 +			if (iSignals&KSignalRTS)
  1.2020 +				SetSignals(KSignalRTS,0);
  1.2021 +			else
  1.2022 +				SetSignals(0,KSignalRTS);
  1.2023 +			}
  1.2024 +		if (!Kern::PowerGood())
  1.2025 +			return;
  1.2026 +		if (hand&KConfigFreeDTR)
  1.2027 +			{
  1.2028 +			if (iSignals&KSignalDTR)
  1.2029 +				SetSignals(KSignalDTR,0);
  1.2030 +			else
  1.2031 +				SetSignals(0,KSignalDTR);
  1.2032 +			}
  1.2033 +		CheckOutputHeld();
  1.2034 +		}
  1.2035 +	else
  1.2036 +		{
  1.2037 +		if (iStatus==EActive)
  1.2038 +			iStatus=EOpen;
  1.2039 +		}
  1.2040 +	}
  1.2041 +
  1.2042 +void DChannelComm::PowerUpDfc(TAny* aPtr)
  1.2043 +	{
  1.2044 +	
  1.2045 +	DChannelComm* d = (DChannelComm*)aPtr;
  1.2046 +	__PM_ASSERT(d->iStandby);
  1.2047 +	if (d->iStatus != EClosed)
  1.2048 +		d->DoPowerUp();
  1.2049 +	else
  1.2050 +		// There is racing Close(): driver was already closed (ECloseMsg) but the DPowerHandler was not destroyed yet.
  1.2051 +		{}
  1.2052 +	d->iStandby = EFalse;
  1.2053 +	d->iPowerHandler->PowerUpDone();
  1.2054 +	if (d->iMsgHeld)
  1.2055 +		{
  1.2056 +		__PM_ASSERT(d->iStatus != EClosed);
  1.2057 +		d->iMsgHeld = EFalse;
  1.2058 +		d->HandleMsg(d->iMsgQ.iMessage);
  1.2059 +		}
  1.2060 +	}
  1.2061 +
  1.2062 +void DChannelComm::PowerDownDfc(TAny* aPtr)
  1.2063 +	{
  1.2064 +	DChannelComm* d = (DChannelComm*)aPtr;
  1.2065 +	__PM_ASSERT(!d->iStandby);
  1.2066 +	d->iStandby = ETrue;
  1.2067 +	if (d->iStatus != EClosed)
  1.2068 +		d->Shutdown();
  1.2069 +	else
  1.2070 +		// There is racing Close(): driver was already closed (ECloseMsg) but the DPowerHandler was not destroyed yet.
  1.2071 +		{}
  1.2072 +	d->iPowerHandler->PowerDownDone();
  1.2073 +	}
  1.2074 +
  1.2075 +DCommPowerHandler::DCommPowerHandler(DChannelComm* aChannel)
  1.2076 +	:	DPowerHandler(KLddName), 
  1.2077 +		iChannel(aChannel)
  1.2078 +	{
  1.2079 +	}
  1.2080 +
  1.2081 +void DCommPowerHandler::PowerUp()
  1.2082 +	{
  1.2083 +	iChannel->iPowerUpDfc.Enque();
  1.2084 +	}
  1.2085 +
  1.2086 +void DCommPowerHandler::PowerDown(TPowerState)
  1.2087 +	{
  1.2088 +	iChannel->iPowerDownDfc.Enque();
  1.2089 +	}
  1.2090 +
  1.2091 +void DChannelComm::FinishBreak(TAny* aSelf)
  1.2092 +	{
  1.2093 +	DChannelComm* self = (DChannelComm*)aSelf;
  1.2094 +	self->QueueFinishBreakDfc();
  1.2095 +	}
  1.2096 +
  1.2097 +void DChannelComm::QueueFinishBreakDfc()
  1.2098 +	{
  1.2099 +	iBreakDfc.Enque();
  1.2100 +	}
  1.2101 +	
  1.2102 +	
  1.2103 +void DChannelComm::FinishBreakDfc(TAny* aSelf)
  1.2104 +	{
  1.2105 +	DChannelComm* self = (DChannelComm*)aSelf;
  1.2106 +	self->FinishBreakImplementation(KErrNone);
  1.2107 +	}
  1.2108 +
  1.2109 +void DChannelComm::FinishBreakImplementation(TInt aError)
  1.2110 +	{
  1.2111 +	if (iStatus==EClosed)
  1.2112 +		{
  1.2113 +		Complete(EBreak, KErrNotReady);
  1.2114 +		}
  1.2115 +	else
  1.2116 +		{
  1.2117 +		BreakOff();
  1.2118 +		Complete(EBreak, aError);
  1.2119 +		}
  1.2120 +
  1.2121 +	// re-setup transmission if needed, for writes after a break
  1.2122 +	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.2123 +	if (iBreakDelayedTx)
  1.2124 +		{
  1.2125 +		iBreakDelayedTx = EFalse;		// protected -> prevent reentrant ISR
  1.2126 +		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.2127 +
  1.2128 +		RestartDelayedTransmission();
  1.2129 +		}
  1.2130 +	else
  1.2131 +		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.2132 +	}
  1.2133 +void DChannelComm::RestartDelayedTransmission()
  1.2134 +	{
  1.2135 +	LOG(("RestartDelayedTransmission()"));
  1.2136 +	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.2137 +	TBool completeTx=EFalse;
  1.2138 +	
  1.2139 +	iBreakDelayedTx = EFalse;		// protected -> prevent reentrant ISR
  1.2140 +	__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.2141 +
  1.2142 +	if (iStatus==EClosed)
  1.2143 +		{
  1.2144 +		irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.2145 +		iTxError = KErrNotReady;		// protected -> changed in signals ISR
  1.2146 +		completeTx = ETrue;
  1.2147 +		}
  1.2148 +
  1.2149 +	else if(IsLineFail(iFailSignals))	// have signals changed in the meantime?
  1.2150 +		{
  1.2151 +		irq = __SPIN_LOCK_IRQSAVE(iLock);
  1.2152 +		iTxError = KErrCommsLineFail;	// protected -> changed in signals ISR
  1.2153 +		completeTx = ETrue;
  1.2154 +		}
  1.2155 +
  1.2156 +	else
  1.2157 +		{
  1.2158 +		InitiateWrite();
  1.2159 +		}
  1.2160 +
  1.2161 +
  1.2162 +	if(completeTx)
  1.2163 +		{
  1.2164 +		iTxError = KErrNone;
  1.2165 +		__SPIN_UNLOCK_IRQRESTORE(iLock, irq);
  1.2166 +		Complete(ETx, iTxError);
  1.2167 +		}
  1.2168 +	}