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 + }