os/kernelhwsrv/kernel/eka/drivers/pbus/pccard/socket.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/drivers/pbus/pccard/socket.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,994 @@
     1.4 +// Copyright (c) 1998-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\pbus\pccard\socket.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include <pccard.h>
    1.22 +#include "cis.h"
    1.23 +
    1.24 +const TInt KFuncGranularity=(KMaxFuncPerCard+1);
    1.25 +const TInt KMemGranularity=2;
    1.26 +
    1.27 +TPccdFuncType FuncType(TUint aFuncCode)
    1.28 +	{
    1.29 +
    1.30 +	if (aFuncCode<=KCisTplFuncIdScsi)
    1.31 +		return((TPccdFuncType)(aFuncCode+1));
    1.32 +	else if (aFuncCode==KCisTplFuncIdVendorSpecific)
    1.33 +		return(EVendorSpecificCard);
    1.34 +	else
    1.35 +		return(EUnknownCard);
    1.36 +	}
    1.37 +
    1.38 +/********************************************
    1.39 + * PC card power supply
    1.40 + ********************************************/
    1.41 +DPcCardVcc::DPcCardVcc(TInt aPsuNum, TInt aMediaChangeNum)
    1.42 +	:	DPBusPsuBase(aPsuNum, aMediaChangeNum)
    1.43 +	{
    1.44 +	}
    1.45 +
    1.46 +TInt DPcCardVcc::SocketVccToMilliVolts(TPccdSocketVcc aVcc)
    1.47 +//
    1.48 +// Converts a TPccdSocketVcc into a integer value - units mV.
    1.49 +//
    1.50 +	{
    1.51 +	switch (aVcc)
    1.52 +		{
    1.53 +		case EPccdSocket_5V0: return(5000);
    1.54 +		case EPccdSocket_3V3: return(3300);
    1.55 +		default: return(0);
    1.56 +		}
    1.57 +	}
    1.58 +
    1.59 +TBool DPcCardVcc::IsLocked()
    1.60 +	{
    1.61 +/*	TInt i;
    1.62 +	Kern::EnterCS();
    1.63 +	for (i=0; i<KMaxPccdSockets; i++)
    1.64 +		{
    1.65 +		DPcCardSocket* pS=(DPcCardSocket*)TheSockets[i];
    1.66 +		if (pS && pS->iVcc==this)
    1.67 +			{
    1.68 +			if (pS->iClientWindows || pS->iActiveConfigs)
    1.69 +				break;
    1.70 +			}
    1.71 +		}
    1.72 +	Kern::LeaveCS();
    1.73 +	return (i<KMaxPccdSockets);
    1.74 +*/
    1.75 +	DPcCardSocket* pS=(DPcCardSocket*)iSocket;
    1.76 +	return (pS->iClientWindows || pS->iActiveConfigs);
    1.77 +	}
    1.78 +
    1.79 +void DPcCardVcc::ReceiveVoltageCheckResult(TInt anError)
    1.80 +	{
    1.81 +	__KTRACE_OPT(KPBUS1,Kern::Printf("DPcCardVcc(%d)::ReceiveVoltageCheckResult(%d)",iPsuNum,anError));
    1.82 +	DPcCardSocket* pS=(DPcCardSocket*)iSocket;
    1.83 +	TInt s=pS->iCardPowerUpState;
    1.84 +	if (s==DPcCardSocket::EWaitForVccReading)
    1.85 +		{
    1.86 +		if (anError==KErrNone)
    1.87 +			{
    1.88 +			SetState(EPsuOnFull);
    1.89 +			pS->iCardPowerUpState=DPcCardSocket::EWaitForReady;
    1.90 +			}
    1.91 +		else
    1.92 +			pS->TerminatePowerUpSequence(KErrCorrupt);
    1.93 +		}
    1.94 +	else if (s!=DPcCardSocket::EInit && s!=DPcCardSocket::EApplyingReset && s!=DPcCardSocket::ECheckVcc)
    1.95 +		DPBusPsuBase::ReceiveVoltageCheckResult(anError);
    1.96 +	}
    1.97 +
    1.98 +/********************************************
    1.99 + * PC card media change
   1.100 + ********************************************/
   1.101 +DPcCardMediaChange::DPcCardMediaChange(TInt aMediaChangeNum)
   1.102 +	: DMediaChangeBase(aMediaChangeNum)
   1.103 +	{
   1.104 +	}
   1.105 +
   1.106 +TInt DPcCardMediaChange::Create()
   1.107 +	{
   1.108 +	return DMediaChangeBase::Create();
   1.109 +	}
   1.110 +
   1.111 +/********************************************
   1.112 + * PC card socket
   1.113 + ********************************************/
   1.114 +void cardPowerUpTick(TAny* aPtr)
   1.115 +	{
   1.116 +	((DPcCardSocket*)aPtr)->iCardPowerUpDfc.Enque();
   1.117 +	}
   1.118 +
   1.119 +void cardPowerUpDfc(TAny* aPtr)
   1.120 +	{
   1.121 +	((DPcCardSocket*)aPtr)->CardPowerUpTick();
   1.122 +	}
   1.123 +
   1.124 +DPcCardSocket::DPcCardSocket(TSocket aSocketNum)
   1.125 +//
   1.126 +// Constructor.
   1.127 +//
   1.128 +	:	DPBusSocket(aSocketNum),
   1.129 +		iCardFuncArray(KFuncGranularity),
   1.130 +		iMemChunks(KMemGranularity),
   1.131 +		iCardPowerUpDfc(cardPowerUpDfc, this, 1)
   1.132 +	{
   1.133 +
   1.134 +	iType=EPBusTypePcCard;
   1.135 +//	iCardPowerUpState=EIdle;
   1.136 +//	iClientWindows=0;
   1.137 +//	iActiveConfigs=0;
   1.138 +	}
   1.139 +
   1.140 +TInt DPcCardSocket::Create(const TDesC* aName)
   1.141 +//
   1.142 +// Create a new Socket. Only created once on kernel initialization so don't
   1.143 +// worry about cleanup if it fails.
   1.144 +//
   1.145 +	{
   1.146 +
   1.147 +	__KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):Create(%lS)",iSocketNumber,aName));
   1.148 +
   1.149 +	TInt r=DPBusSocket::Create(aName);
   1.150 +	if (r!=KErrNone)
   1.151 +		return r;
   1.152 +	iCardPowerUpDfc.SetDfcQ(&iDfcQ);
   1.153 +
   1.154 +	// Create card function array - add and remove a dummy function to pre-allocate array memory.
   1.155 +	// This way, adding new functions to array never causes any memory allocation.
   1.156 +	r=AddNewFunc(0,EPccdAttribMem);				// Add dummy function
   1.157 +	if (r!=KErrNone)
   1.158 +		return r;
   1.159 +	delete iCardFuncArray[0];					// Destroy dummy function
   1.160 +	iCardFuncArray.Remove(0);					// Remove pointer to dummy from array
   1.161 +
   1.162 +	// Now allocate the permanent attribute memory chunk. Don't bother about what
   1.163 +	// access speed we asign, it gets set each time we subsequently access the chunk.
   1.164 +	TPccdChnk chnk(EPccdAttribMem,0,KDefaultAttribMemSize);
   1.165 +	r=iAttribWin.Create(this,chnk,EAcSpeed300nS,KPccdChunkPermanent|KPccdChunkShared|KPccdChunkSystemOwned);
   1.166 +	return r;
   1.167 +	}
   1.168 +
   1.169 +void DPcCardSocket::ResetPowerUpState()
   1.170 +	{
   1.171 +	__KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):ResetPowerUpState",iSocketNumber));
   1.172 +	if (iCardPowerUpState!=EIdle)
   1.173 +		{
   1.174 +		iCardPowerUpTimer.Cancel();
   1.175 +		iCardPowerUpDfc.Cancel();
   1.176 +		iCardPowerUpState=EIdle;
   1.177 +		}
   1.178 +	}
   1.179 +
   1.180 +void DPcCardSocket::Reset1()
   1.181 +	{
   1.182 +	__KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):Reset1",iSocketNumber));
   1.183 +	ResetPowerUpState();
   1.184 +	}
   1.185 +
   1.186 +void DPcCardSocket::Reset2()
   1.187 +//
   1.188 +// Reset the socket (called to remove any allocated memory following a
   1.189 +// media change event).
   1.190 +//
   1.191 +	{
   1.192 +
   1.193 +	__KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):Rst2",iSocketNumber));
   1.194 +	// Destroy all the function objects
   1.195 +	TInt i;
   1.196 +	for (i=CardFuncCount()-1;i>=0;i--)
   1.197 +		{
   1.198 +		delete iCardFuncArray[i];
   1.199 +		iCardFuncArray.Remove(i);		// Now remove from array (doesn't cause memory dealloc).
   1.200 +		}
   1.201 +	iActiveConfigs=0;
   1.202 +
   1.203 +	// Destroy all the non-permanent Pc Card chunks
   1.204 +	for (i=(iMemChunks.Count()-1);i>=0;i--)
   1.205 +		{
   1.206 +		if ( iMemChunks[i]->IsRemovable() )
   1.207 +			iMemChunks[i]->Close();
   1.208 +		}
   1.209 +	iMemChunks.Compress();
   1.210 +	}
   1.211 +
   1.212 +void DPcCardSocket::Restore()
   1.213 +//
   1.214 +// Restore the socket. Normally called when restoring a socket after it has been powered 
   1.215 +// down due to inactivity (but not media change)
   1.216 +//
   1.217 +	{	
   1.218 +	TInt i;
   1.219 +	TPcCardFunction *cf;
   1.220 +	for (i=CardFuncCount()-1;i>=0;i--)
   1.221 +		{
   1.222 +		cf=iCardFuncArray[i];
   1.223 +
   1.224 +		TUint8 index;
   1.225 +		if ((index=(TUint8)cf->ConfigOption())!=KInvalidConfOpt && cf->IsRestorableConfig())
   1.226 +			WriteConfigReg(i,KConfigOptionReg,index);
   1.227 +		}
   1.228 +	}
   1.229 +
   1.230 +void DPcCardSocket::RemoveChunk(DPccdChunkBase *aChunk)
   1.231 +//
   1.232 +// Remove a chunk from this socket. 
   1.233 +//	
   1.234 +	{
   1.235 +	TInt i;
   1.236 +	for (i=0;i<iMemChunks.Count();i++)
   1.237 +		{
   1.238 +		if (iMemChunks[i]==aChunk)
   1.239 +			{
   1.240 +			iMemChunks.Remove(i);
   1.241 +			iMemChunks.Compress();
   1.242 +			return;
   1.243 +			}
   1.244 +		}
   1.245 +	}
   1.246 +
   1.247 +EXPORT_C TInt DPcCardSocket::RequestConfig(TInt aCardFunc,DBase *aClientID,TPcCardConfig &anInfo,TUint aFlag)
   1.248 +//
   1.249 +// Configure the card.
   1.250 +//
   1.251 +	{
   1.252 +
   1.253 +	__KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):RequestConfig(F:%d O:%xH B:%xH L:%xH)",iSocketNumber,aCardFunc,\
   1.254 +										   anInfo.iConfigOption,anInfo.iConfigBaseAddr,anInfo.iRegPresent));
   1.255 +	if (!IsValidCardFunc(aCardFunc))
   1.256 +		return(KErrArgument);
   1.257 +	// Check that this function isn't configured already
   1.258 +	TPcCardFunction *cf=iCardFuncArray[aCardFunc];
   1.259 +	if (cf->IsConfigured())
   1.260 +		return(KErrInUse);	   // Its already configured.
   1.261 +
   1.262 +	// If configuration registers are within attribute chunk then configure the
   1.263 +	// card (rather than use the registers present info, assume all registers are
   1.264 +	// present - ie size of mask).
   1.265 +	if (anInfo.iConfigBaseAddr+(sizeof(anInfo.iRegPresent)<<1)>KDefaultAttribMemSize)
   1.266 +		return(KErrNotSupported);
   1.267 +	anInfo.iConfigOption&=(KConfOptLevIReqM|KConfOptConfM); // Mustn't allow msb - KInvalidConfOpt
   1.268 +	TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS;
   1.269 +	iAttribWin.SetAccessSpeed(sp);
   1.270 +	iAttribWin.SetupChunkHw();
   1.271 +	iAttribWin.Write(anInfo.iConfigBaseAddr,(TUint8*)&anInfo.iConfigOption,1);
   1.272 +
   1.273 +	cf->SetConfigRegMask(anInfo.iRegPresent);
   1.274 +	cf->SetConfigBaseAddr(anInfo.iConfigBaseAddr);
   1.275 +	cf->SetConfigOption(anInfo.iConfigOption,aClientID,aFlag);
   1.276 +	__e32_atomic_add_ord32(&iActiveConfigs, 1);
   1.277 +	return(KErrNone);
   1.278 +	}
   1.279 +
   1.280 +EXPORT_C void DPcCardSocket::ReleaseConfig(TInt aCardFunc,DBase *aClientID)
   1.281 +//
   1.282 +// Return card to memory only config.
   1.283 +//
   1.284 +	{
   1.285 +
   1.286 +	__KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):ReleaseConfig(F:%d)",iSocketNumber,aCardFunc));
   1.287 +	if (IsValidCardFunc(aCardFunc))
   1.288 +		{
   1.289 +		TPcCardFunction *cf=iCardFuncArray[aCardFunc];
   1.290 +		if (cf->IsConfiguredByClient(aClientID))
   1.291 +			{
   1.292 +			if (iState==EPBusOn && Kern::PowerGood())
   1.293 +				WriteConfigReg(aCardFunc,KConfigOptionReg,0); // Restore Config. Option register
   1.294 +
   1.295 +			cf->SetConfigRegMask(0);
   1.296 +			cf->SetConfigBaseAddr(0);	
   1.297 +			cf->SetConfigOption(KInvalidConfOpt,NULL,0);
   1.298 +			__e32_atomic_add_ord32(&iActiveConfigs, TUint32(-1));
   1.299 +			}
   1.300 +		}
   1.301 +	}
   1.302 +
   1.303 +EXPORT_C TInt DPcCardSocket::ReadConfigReg(TInt aCardFunc,TInt aRegOffset,TUint8 &aVal)
   1.304 +//
   1.305 +// Read from a specified configuration register. (We return an error if the RegPres mask
   1.306 +// indicates the register isn't present but still attempt the read).
   1.307 +//
   1.308 +	{
   1.309 +	TInt offset, err;
   1.310 +	if (!IsValidCardFunc(aCardFunc)|| iState!=EPBusOn || !Kern::PowerGood())
   1.311 +		err=KErrArgument;
   1.312 +	else
   1.313 +		{
   1.314 +		if ((err=iCardFuncArray[aCardFunc]->ConfigRegAddress(aRegOffset,offset))==KErrNone||err==KErrNotSupported)
   1.315 +			{
   1.316 +			TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS;
   1.317 +			iAttribWin.SetAccessSpeed(sp);
   1.318 +			iAttribWin.SetupChunkHw();
   1.319 +			iAttribWin.Read(offset,&aVal,1);
   1.320 +			}
   1.321 +		}
   1.322 +	__KTRACE_OPT(KPBUS1,Kern::Printf("<Skt(%d):ReadConfigReg-%d",iSocketNumber,err));
   1.323 +	return(err);
   1.324 +	}
   1.325 +
   1.326 +EXPORT_C TInt DPcCardSocket::WriteConfigReg(TInt aCardFunc,TInt aRegOffset,const TUint8 aVal)
   1.327 +//
   1.328 +// Write to a specified configuration register. (We return an error if the RegPres mask
   1.329 +// indicates the register isn't present but still attempt the write).
   1.330 +//
   1.331 +	{
   1.332 +	TInt offset, err;
   1.333 +	if (!IsValidCardFunc(aCardFunc)|| iState!=EPBusOn || !Kern::PowerGood())
   1.334 +		err=KErrArgument;
   1.335 +	else
   1.336 +		{
   1.337 +		if ((err=iCardFuncArray[aCardFunc]->ConfigRegAddress(aRegOffset,offset))==KErrNone||err==KErrNotSupported)
   1.338 +			{
   1.339 +			TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS;
   1.340 +			iAttribWin.SetAccessSpeed(sp);
   1.341 +			iAttribWin.SetupChunkHw();
   1.342 +			iAttribWin.Write(offset,&aVal,1);
   1.343 +			}
   1.344 +		}
   1.345 +	__KTRACE_OPT(KPBUS1,Kern::Printf("<Skt(%d):WriteConfigReg-%d",iSocketNumber,err));
   1.346 +	return(err);
   1.347 +	}
   1.348 +
   1.349 +const TInt KReadCisBufferSize=0x80;   // 128 Bytes
   1.350 +TInt DPcCardSocket::ReadCis(TPccdMemType aMemType,TInt aPos,TDes8 &aDes,TInt aLen)
   1.351 +//
   1.352 +// Read from CIS 
   1.353 +//
   1.354 +	{
   1.355 +
   1.356 +	__KTRACE_OPT(KPBUS2,Kern::Printf(">Skt(%d):ReadCis(LE:%xH PO:%d TY:%d)",iSocketNumber,aLen,aPos,aMemType));
   1.357 +	RPccdWindow newWin;
   1.358 +	RPccdWindow* win=&newWin;
   1.359 +	TBool needNewChunk=ETrue;
   1.360 +	TInt cisE=(aPos+aLen);
   1.361 +	TInt incrm=1;
   1.362 +	if (aMemType==EPccdAttribMem)
   1.363 +		{
   1.364 +		incrm=2;		// Read every other byte
   1.365 +		cisE<<=1;		
   1.366 +		aPos<<=1;
   1.367 +		if (cisE<=(TInt)KDefaultAttribMemSize)
   1.368 +			{
   1.369 +			needNewChunk=EFalse;
   1.370 +			win=&iAttribWin;
   1.371 +			}
   1.372 +		}
   1.373 +
   1.374 +	if (needNewChunk)
   1.375 +		{
   1.376 +		TPccdChnk chnk(aMemType,aPos,(cisE-aPos));
   1.377 +		TInt r=newWin.Create(this,chnk,EAcSpeed300nS,KPccdChunkShared|KPccdChunkSystemOwned);
   1.378 +		if (r!=KErrNone)
   1.379 +			return(r);
   1.380 +		cisE-=aPos;
   1.381 +		aPos=0;
   1.382 +		}
   1.383 +
   1.384 +	TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS;
   1.385 +	win->SetAccessSpeed(sp);
   1.386 +	win->SetupChunkHw();
   1.387 +	aDes.Zero();
   1.388 +	TText8 buf[KReadCisBufferSize];
   1.389 +	TInt s;
   1.390 +	for (;aPos<cisE;aPos+=s)
   1.391 +		{
   1.392 +		s=Min(KReadCisBufferSize,(cisE-aPos));
   1.393 +		win->Read(aPos,&buf[0],s);
   1.394 +		for (TInt i=0;i<s;i+=incrm)
   1.395 +			aDes.Append((TChar)buf[i]);   
   1.396 +		} 
   1.397 +
   1.398 +	if (needNewChunk)
   1.399 +		newWin.Close();
   1.400 +	return(KErrNone);
   1.401 +	}
   1.402 +
   1.403 +TInt DPcCardSocket::AddNewFunc(TUint32 anOffset,TPccdMemType aMemType)
   1.404 +//
   1.405 +// Create a new card function and append it to the function array
   1.406 +//
   1.407 +	{
   1.408 +
   1.409 +	__KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):AddNewFunc(T:%d)",iSocketNumber,aMemType));
   1.410 +	TInt r=KErrNoMemory;
   1.411 +	TPcCardFunction* cf=new TPcCardFunction(anOffset,aMemType);
   1.412 +	if (cf)
   1.413 +		{
   1.414 +		r=iCardFuncArray.Append(cf);
   1.415 +		if (r!=KErrNone)
   1.416 +			delete cf;
   1.417 +		}
   1.418 +	return r;
   1.419 +	}
   1.420 +
   1.421 +TPcCardFunction *DPcCardSocket::CardFunc(TInt aCardFunc)
   1.422 +// 
   1.423 +// Get a reference to a specific card function from the function array 
   1.424 +//
   1.425 +	{
   1.426 +												   
   1.427 +	__ASSERT_ALWAYS(IsValidCardFunc(aCardFunc),PcCardPanic(EPcCardBadFunctionNumber));
   1.428 +	return iCardFuncArray[aCardFunc];
   1.429 +	}
   1.430 +
   1.431 +TBool DPcCardSocket::IsConfigLocked()
   1.432 +//
   1.433 +// Returns ETrue if this socket contains a card function which is currently configured.
   1.434 +//
   1.435 +	{
   1.436 +//	TInt i;
   1.437 +//	for (i=CardFuncCount()-1;i>=0;i--)
   1.438 +//		{
   1.439 +//		if (iCardFuncArray[i]->IsConfigured())
   1.440 +//			return(ETrue);
   1.441 +//		}
   1.442 +//	return(EFalse);
   1.443 +	return (iActiveConfigs!=0);
   1.444 +	}
   1.445 +
   1.446 +TBool DPcCardSocket::IsMemoryLocked()
   1.447 +//
   1.448 +// Returns ETrue if any PC Card memory chunks are allocated on this socket.
   1.449 +//
   1.450 +	{
   1.451 +
   1.452 +//	TInt i;
   1.453 +//	for (i=iMemChunks.Count()-1;i>=0;i--)
   1.454 +//		{
   1.455 +//		if ( iMemChunks[i]->IsLocked() )
   1.456 +//			return(ETrue);
   1.457 +//		}
   1.458 +//	return(EFalse);
   1.459 +	return (iClientWindows!=0);
   1.460 +	}
   1.461 +
   1.462 +TPccdSocketVcc DPcCardSocket::VccSetting()
   1.463 +//
   1.464 +// Return voltage setting that this socket is currently set for
   1.465 +//
   1.466 +	{
   1.467 +
   1.468 +	return ((DPcCardVcc*)iVcc)->VoltageSetting();
   1.469 +	}
   1.470 +
   1.471 +EXPORT_C TInt DPcCardSocket::VerifyCard(TPccdType &aType)
   1.472 +//
   1.473 +// Return information about the type of card present 
   1.474 +//
   1.475 +	{
   1.476 +
   1.477 +	__KTRACE_OPT(KPBUS1,Kern::Printf(">Cntrl:VerifyCard(S:%d)",iSocketNumber));
   1.478 +	// The data we want is stored off-card, so it doesn't actually need to be
   1.479 +	// powered but we need to have read CIS format.
   1.480 +	TInt err=KErrNone;
   1.481 +    if (CardIsReadyAndVerified()==KErrNone)
   1.482 +		{
   1.483 +		aType.iFuncCount=CardFuncCount();
   1.484 +		for (TInt i=(aType.iFuncCount-1);i>=0;i--)
   1.485 +			aType.iFuncType[i]=CardFunc(i)->FuncType();
   1.486 +		}
   1.487 +	else
   1.488 +		err=KErrNotReady;
   1.489 +
   1.490 +	__KTRACE_OPT(KPBUS1,Kern::Printf("<Cntrl:VerifyCard(S:%d T:%d)-%d",iSocketNumber,(TInt)aType.iFuncType[0],err));
   1.491 +	return(err);
   1.492 +	}
   1.493 +
   1.494 +TInt DPcCardSocket::CardIsReadyAndVerified()
   1.495 +//
   1.496 +// Returns KErrNone when specified card is powered and ready (ie has had h/w reset) and
   1.497 +// a basic parsing of CIS has been performed (card functions detected).
   1.498 +//
   1.499 +	{
   1.500 +
   1.501 +	TInt r=KErrNotReady;
   1.502 +	if (CardIsReady())
   1.503 +		{
   1.504 +		r=KErrNone;
   1.505 +		// Check if card function(s) have been determined (there is always at
   1.506 +		// least a global function record if basic parsing performed).
   1.507 +		if (!IsVerified())
   1.508 +			r=GetCisFormat();
   1.509 +		}
   1.510 +
   1.511 +	__KTRACE_OPT(KPBUS1,Kern::Printf("<Cntrl:CardRdyAndVerif(S:%d)-%xH",iSocketNumber,r));
   1.512 +	return r;
   1.513 +	}
   1.514 +
   1.515 +TBool DPcCardSocket::CardIsReady()
   1.516 +	{
   1.517 +	TBool r=(iState==EPBusOn && Kern::PowerGood());
   1.518 +	__KTRACE_OPT(KPBUS1,Kern::Printf("CardIsReady: %d",r));
   1.519 +	return r;
   1.520 +	}
   1.521 +
   1.522 +TBool DPcCardSocket::CardIsPowered()
   1.523 +	{
   1.524 +	return !iVcc->IsOff();
   1.525 +	}
   1.526 +
   1.527 +TInt DPcCardSocket::GetCisFormat()
   1.528 +//
   1.529 +// Determine the type of card present by parsing the entire CIS. If a 
   1.530 +// Multi-function card is present then parse each CIS.
   1.531 +//
   1.532 +	{
   1.533 +
   1.534 +	__KTRACE_OPT(KPBUS1,Kern::Printf(">GetCisFormat (S:%d)",iSocketNumber));
   1.535 +
   1.536 +	TInt r=AddNewFunc(0,EPccdAttribMem);		// We always have 1st CIS
   1.537 +	if (r!=KErrNone)
   1.538 +		return r;
   1.539 +	if (ValidateCis(0)!=KErrNone)				// Can't use this until func added
   1.540 +		return KErrCorrupt;
   1.541 +	TCisReader cisRd;
   1.542 +	cisRd.iSocket=this;
   1.543 +	cisRd.DoSelectCis(0);
   1.544 +	TPccdFuncType firstFuncType;
   1.545 +	// Check for a multi-function card, search the global CIS (attribute 
   1.546 +	// memory - addr 0) for a KCisTplLongLinkMfc tuple.
   1.547 +	TBuf8<KLargeTplBufSize> tpl;
   1.548 +	if (cisRd.DoFindReadTuple(KCisTplLongLinkMfc,tpl,KPccdReturnLinkTpl)==KErrNone)
   1.549 +		{
   1.550 +		// Multi-Function card 
   1.551 +		firstFuncType=EGlobalCard;
   1.552 +		const TUint8 *tplPtr=tpl.Ptr()+2; // First tuple after link
   1.553 +		TInt funcCount=*tplPtr++;
   1.554 +
   1.555 +		// Add a card function object to the socket for each entry in KCisTplLongLinkMfc tuple
   1.556 +		TPccdMemType memType;
   1.557 +		TUint32 lnkAdr;
   1.558 +		TInt i;
   1.559 +		for (i=0;i<funcCount;i++)
   1.560 +			{
   1.561 +			memType=(*tplPtr++)?EPccdCommon8Mem:EPccdAttribMem;
   1.562 +			TInt j;
   1.563 +			for (lnkAdr=0,j=0;j<4;j++)		// Convert link address from string to unsigned long
   1.564 +				lnkAdr += (*tplPtr++) << (8*j);
   1.565 +			r=AddNewFunc(lnkAdr,memType);
   1.566 +			if (r!=KErrNone)
   1.567 +				return r;
   1.568 +			if (ValidateCis(i+1)!=KErrNone) // Can't use this until func added
   1.569 +				return KErrCorrupt;
   1.570 +			}
   1.571 +		// Parse the CIS of each card function looking for a KCisTplFuncId tuple
   1.572 +		for (i=1;i<=funcCount;i++)
   1.573 +			{
   1.574 +			cisRd.DoSelectCis(i);
   1.575 +			TPccdFuncType ft;
   1.576 +			if (cisRd.DoFindReadTuple(KCisTplFuncId,tpl,0)==KErrNone)
   1.577 +				ft=FuncType(tpl[2]);
   1.578 +			else
   1.579 +				ft=EUnknownCard;
   1.580 +			CardFunc(i)->SetFuncType(ft);
   1.581 +			}
   1.582 +		}
   1.583 +	else
   1.584 +		{
   1.585 +		// Single Function card 
   1.586 +		cisRd.Restart();
   1.587 +		if (cisRd.DoFindReadTuple(KCisTplFuncId,tpl,0)==KErrNone)
   1.588 +			firstFuncType=FuncType(tpl[2]); 
   1.589 +		else
   1.590 +			firstFuncType=EUnknownCard; 
   1.591 +		}
   1.592 +
   1.593 +	CardFunc(0)->SetFuncType(firstFuncType);
   1.594 +	__KTRACE_OPT(KPBUS1,Kern::Printf("<GetCisFormat(T:%d)",firstFuncType));
   1.595 +	return KErrNone;
   1.596 +	}
   1.597 +
   1.598 +TInt DPcCardSocket::ValidateCis(TInt aCardFunc)
   1.599 +//
   1.600 +// Attempt to walk though entire CIS.
   1.601 +//
   1.602 +	{
   1.603 +
   1.604 +	TCisReader cisRd;
   1.605 +	cisRd.iSocket=this;
   1.606 +	TBuf8<KLargeTplBufSize> tpl;
   1.607 +	TInt j=0,err;
   1.608 +	if ((err=cisRd.DoSelectCis(aCardFunc))==KErrNone)
   1.609 +		{
   1.610 +		for (j=0;j<KMaxTuplesPerCis;j++)
   1.611 +			{
   1.612 +			err=cisRd.DoFindReadTuple(KPccdNonSpecificTpl,tpl,(KPccdFindOnly|KPccdReturnLinkTpl|KPccdReportErrors));
   1.613 +			if (err!=KErrNone)
   1.614 +				break;
   1.615 +			}
   1.616 +		if (j>=KMaxTuplesPerCis)
   1.617 +			err=KErrCorrupt;
   1.618 +		if (err==KErrNotFound)
   1.619 +			err=KErrNone;
   1.620 +		}
   1.621 +	__KTRACE_OPT(KPBUS1,Kern::Printf("<Skt:ValidateCis(S:%d F:%d Tuples:%d)-%d",iSocketNumber,aCardFunc,j,err));
   1.622 +	return(err);
   1.623 +	}
   1.624 +
   1.625 +void DPcCardSocket::InitiatePowerUpSequence()
   1.626 +	{
   1.627 +	__KTRACE_OPT(KPBUS1,Kern::Printf("DPcCardSocket(%d)::InitiatePowerUpSequence",iSocketNumber));
   1.628 +	// Check if battery is too low
   1.629 +//	TSupplyStatus ss=(TSupplyStatus)iMachineInfo.iDisableOnLowBattery;
   1.630 +//	if (ss!=EZero)
   1.631 +//		{
   1.632 +//		TSupplyInfoV1 info;
   1.633 +//		Hal::SupplyInfo(info); 
   1.634 +//		if (info.iMainBatteryStatus<ss && !info.iExternalPowerPresent)
   1.635 +//			{
   1.636 +//			iSocket[aSocket]->SetSocketStatus(ESocketBatTooLow);
   1.637 +//			rs=KErrBadPower;
   1.638 +//			break;
   1.639 +//			}
   1.640 +//		}
   1.641 +
   1.642 +	// Check the state of the Voltage sense line
   1.643 +	TSocketIndicators ind;
   1.644 +	Indicators(ind);
   1.645 +	TUint v=(TUint)ind.iVoltSense & ((DPcCardVcc*)iVcc)->VoltageSupported();
   1.646 +	if (v==0)
   1.647 +		{
   1.648 +		__KTRACE_OPT(KPBUS1,Kern::Printf("InitiatePowerUpSequence(S:%d)-Voltage sense problem(%d)",iSocketNumber,ind.iVoltSense));
   1.649 +		iVcc->SetCurrLimited();   // Not totally true but has effect.
   1.650 +		PowerUpSequenceComplete(KErrCorrupt);
   1.651 +		return;
   1.652 +		}
   1.653 +	TPccdSocketVcc sVcc=(v&KPccdVcc_3V3)?EPccdSocket_3V3:EPccdSocket_5V0; // ??? What about xVx / yVy 
   1.654 +	((DPcCardVcc*)iVcc)->SetVoltage(sVcc);
   1.655 +
   1.656 +	// Power up card (current limited).
   1.657 +	__KTRACE_OPT(KPBUS1,Kern::Printf("InitiatePowerUpSequence(S:%d)-Apply Vcc",iSocketNumber));
   1.658 +	if (iVcc->SetState(EPsuOnCurLimit) != KErrNone)
   1.659 +		{
   1.660 +		__KTRACE_OPT(KPBUS1,Kern::Printf("InitiatePowerUpSequence(S:%d)-Vcc problem",iSocketNumber));
   1.661 +		iVcc->SetState(EPsuOff);
   1.662 +		iVcc->SetCurrLimited();
   1.663 +		PowerUpSequenceComplete(KErrGeneral);
   1.664 +		return;
   1.665 +		}
   1.666 +	iCardPowerUpState=EInit;
   1.667 +	iCardPowerUpTickCount=0;
   1.668 +	iCardPowerUpResetLen=KResetOnDefaultLen;
   1.669 +	iCardPowerUpPauseLen=KResetOffDefaultLen;
   1.670 +	iCardPowerUpTimer.Periodic(KPccdPowerUpReqInterval,cardPowerUpTick,this);
   1.671 +	}
   1.672 +
   1.673 +void DPcCardSocket::TerminatePowerUpSequence(TInt aResult)
   1.674 +	{
   1.675 +	__KTRACE_OPT(KPBUS1,Kern::Printf("DPcCardSocket(%d)::TerminatePowerUpSequence result %d",iSocketNumber,aResult));
   1.676 +	ResetPowerUpState();
   1.677 +	if (aResult==KErrNone)
   1.678 +		Restore();
   1.679 +	PowerUpSequenceComplete(aResult);
   1.680 +	}
   1.681 +
   1.682 +void DPcCardSocket::CardPowerUpTick()
   1.683 +	{
   1.684 +	__KTRACE_OPT(KPBUS1,Kern::Printf("CardPowerUpTick S:%d Elapsed %d State %d",iSocketNumber,iCardPowerUpTickCount,iCardPowerUpState));
   1.685 +	if (++iCardPowerUpTickCount>KPwrUpTimeOut)
   1.686 +		{
   1.687 +		iVcc->SetState(EPsuOff);	// should leave this to timeout
   1.688 +		TerminatePowerUpSequence(KErrTimedOut);
   1.689 +		return;
   1.690 +		}
   1.691 +	switch (iCardPowerUpState)
   1.692 +		{
   1.693 +		case EInit:
   1.694 +			HwReset(ETrue);		// Apply reset - Turns on interface
   1.695 +			iCardPowerUpState=EApplyingReset;
   1.696 +			break;
   1.697 +		case EApplyingReset:
   1.698 +			if (iCardPowerUpTickCount>iCardPowerUpResetLen)
   1.699 +				{
   1.700 +				HwReset(EFalse);	// remove reset
   1.701 +				iCardPowerUpState=ECheckVcc;
   1.702 +				}
   1.703 +			break;
   1.704 +		case ECheckVcc:
   1.705 +			{
   1.706 +			iCardPowerUpState=EWaitForVccReading;
   1.707 +			TInt cv=iVcc->CheckVoltage(KPsuChkOnPwrUp);
   1.708 +			if (cv==KErrNotSupported)
   1.709 +				iCardPowerUpState=EWaitForReady;
   1.710 +			else if (cv!=KErrNone)
   1.711 +				TerminatePowerUpSequence(cv);
   1.712 +			break;
   1.713 +			}
   1.714 +		case EWaitForVccReading:
   1.715 +			break;
   1.716 +		case EWaitForReady:
   1.717 +			if (Ready())
   1.718 +				{
   1.719 +				iCardPowerUpState=EPauseAfterReady; // Card is ready
   1.720 +				// Its effectively powered up now so reset the elapsed time and use it 
   1.721 +				// to measure pause after reset (ie this is limited to KPwrUpTimeOut too).
   1.722 +				iCardPowerUpTickCount=0;
   1.723 +				}
   1.724 +			break;
   1.725 +		case EPauseAfterReady:
   1.726 +			if (iCardPowerUpTickCount>=iCardPowerUpPauseLen)
   1.727 +				{
   1.728 +				// power-up sequence is complete
   1.729 +				TerminatePowerUpSequence(KErrNone);
   1.730 +				}
   1.731 +			break;
   1.732 +		}
   1.733 +	}
   1.734 +
   1.735 +/********************************************
   1.736 + * PC card memory chunk
   1.737 + ********************************************/
   1.738 +DPccdChunkBase::DPccdChunkBase()
   1.739 +//
   1.740 +// Constructor
   1.741 +//
   1.742 +	{
   1.743 +//	iSocket=NULL;
   1.744 +//	iCacheable=EFalse;
   1.745 +	}
   1.746 +
   1.747 +TInt DPccdChunkBase::Create(DPcCardSocket* aSocket, TPccdChnk aChunk, TUint aFlag)
   1.748 +//
   1.749 +// Create a chunk of Pc Card h/w.
   1.750 +//
   1.751 +	{
   1.752 +	iSocket=aSocket;
   1.753 +	iChnk=aChunk;
   1.754 +	iCacheable=(aFlag&KPccdChunkCacheable);
   1.755 +	return DoCreate(aChunk,aFlag);
   1.756 +	}
   1.757 +
   1.758 +DPccdChunkBase::~DPccdChunkBase()
   1.759 +//
   1.760 +// Destructor
   1.761 +//
   1.762 +	{
   1.763 +	__KTRACE_OPT(KPBUS1,Kern::Printf(">DPccdChunkBase destruct %08x",this));
   1.764 +	}
   1.765 +
   1.766 +void DPccdChunkBase::Close()
   1.767 +//
   1.768 +// Destructor
   1.769 +//
   1.770 +	{
   1.771 +	__KTRACE_OPT(KPBUS1,Kern::Printf(">DPccdChunkBase::Close() %08x",this));
   1.772 +
   1.773 +	// Disconnect all the Pc Card windows and then delete chunk
   1.774 +	SDblQueLink* pW=iWindowQ.iA.iNext;
   1.775 +	while (pW!=&iWindowQ.iA)
   1.776 +		{
   1.777 +		RPccdWindow& w=*(RPccdWindow*)pW;
   1.778 +		pW=pW->iNext;
   1.779 +		w.Close();	// closing last window deletes chunk
   1.780 +		}
   1.781 +	__KTRACE_OPT(KPBUS1,Kern::Printf("<DPccdChunkBase::Close() %08x",this));
   1.782 +	}
   1.783 +
   1.784 +TBool DPccdChunkBase::IsRemovable()
   1.785 +//
   1.786 +// Check if this chunk has any permanent windows.
   1.787 +//
   1.788 +	{
   1.789 +	return (iPermanentWindows==0);
   1.790 +	}
   1.791 +
   1.792 +TBool DPccdChunkBase::IsLocked()
   1.793 +//
   1.794 +// Check if this chunk has any windows which are allocated to clients of the PC Card
   1.795 +// Controller (as opposed to the Controller itself).
   1.796 +//
   1.797 +	{
   1.798 +	return (iWindows>iSystemWindows);
   1.799 +	}
   1.800 +
   1.801 +TInt DPccdChunkBase::AllocateWinCheck(TPccdChnk aWin,TUint aFlag)
   1.802 +//
   1.803 +// Check if it is possible to create the specified window from this chunk.
   1.804 +//
   1.805 +	{
   1.806 +	// Check if they are of compatible type
   1.807 +	if (!IsTypeCompatible(aWin.iMemType))
   1.808 +		return(KErrNotFound);
   1.809 +
   1.810 +	// For a success, the requested window must lie entirely within this chunk.
   1.811 +	TUint32 chnkEnd=(iChnk.iMemBaseAddr+iChnk.iMemLen-1);
   1.812 +	TUint32 winEnd=(aWin.iMemBaseAddr+aWin.iMemLen-1);
   1.813 +	TBool startIsInChnk=(aWin.iMemBaseAddr>=iChnk.iMemBaseAddr && aWin.iMemBaseAddr<=chnkEnd);
   1.814 +	TBool endIsInChnk=(winEnd>=iChnk.iMemBaseAddr && winEnd<=chnkEnd);
   1.815 +	if (startIsInChnk&&endIsInChnk)
   1.816 +		{
   1.817 +		// Possible success - first check the cache options are compatible
   1.818 +		if (!(aFlag|KPccdChunkCacheable)&&iCacheable)
   1.819 +			return(KErrAccessDenied);
   1.820 +
   1.821 +		// Now check that the requested window isn't already allocated
   1.822 +		SDblQueLink* pW=iWindowQ.iA.iNext;
   1.823 +		while (pW!=&iWindowQ.iA)
   1.824 +			{
   1.825 +			RPccdWindow& w=*(RPccdWindow*)pW;
   1.826 +			pW=pW->iNext;
   1.827 +			if (w.Overlap(aWin.iMemBaseAddr-iChnk.iMemBaseAddr,aWin.iMemLen) )
   1.828 +				return(KErrAccessDenied);
   1.829 +			}
   1.830 +		return(KErrNone);
   1.831 +		}
   1.832 +	if (startIsInChnk||endIsInChnk)
   1.833 +		return(KErrAccessDenied);	// Requested window is partly in this chunk.
   1.834 +	return(KErrNotFound);
   1.835 +	}
   1.836 +
   1.837 +void DPccdChunkBase::AddWindow(RPccdWindow *aWindow)
   1.838 +//
   1.839 +// Add a window to this chunk.
   1.840 +//
   1.841 +	{
   1.842 +	iWindowQ.Add(aWindow);
   1.843 +//	Kern::EnterCS();		Not needed since a single thread is used
   1.844 +	iWindows++;
   1.845 +	if (aWindow->IsPermanent())
   1.846 +		iPermanentWindows++;
   1.847 +	if (aWindow->IsShareable())
   1.848 +		iShareableWindows++;
   1.849 +	if (aWindow->IsSystemOwned())
   1.850 +		iSystemWindows++;
   1.851 +	else
   1.852 +		iSocket->iClientWindows++;
   1.853 +//	Kern::LeaveCS();
   1.854 +	aWindow->iChunk=this;
   1.855 +	}
   1.856 +
   1.857 +void DPccdChunkBase::RemoveWindow(RPccdWindow *aWindow)
   1.858 +//
   1.859 +// Remove a window from this chunk (even if it's permanent). 
   1.860 +//	
   1.861 +	{
   1.862 +
   1.863 +	if (aWindow->iNext && aWindow->iChunk==this)
   1.864 +		{
   1.865 +		aWindow->Deque();
   1.866 +		aWindow->iNext=NULL;
   1.867 +//		Kern::EnterCS();	Not needed since a single thread is used
   1.868 +		iWindows--;
   1.869 +		if (aWindow->IsPermanent())
   1.870 +			iPermanentWindows--;
   1.871 +		if (aWindow->IsShareable())
   1.872 +			iShareableWindows--;
   1.873 +		if (aWindow->IsSystemOwned())
   1.874 +			iSystemWindows--;
   1.875 +		else
   1.876 +			iSocket->iClientWindows--;
   1.877 +//		Kern::LeaveCS();
   1.878 +		if (iWindows==0)
   1.879 +			{
   1.880 +			iSocket->RemoveChunk(this);
   1.881 +			delete this;
   1.882 +			}
   1.883 +		}
   1.884 +	}
   1.885 +
   1.886 +/********************************************
   1.887 + * PC card memory window
   1.888 + ********************************************/
   1.889 +EXPORT_C RPccdWindow::RPccdWindow()
   1.890 +//
   1.891 +// Constructor
   1.892 +//
   1.893 +	: iAccessSpeed(EAcSpeedInValid),iMemType(EPccdAttribMem),iOffset(0),iLen(0),iType(0)
   1.894 +	{
   1.895 +	iNext=NULL;
   1.896 +	iChunk=NULL;
   1.897 +	}
   1.898 +
   1.899 +EXPORT_C TInt RPccdWindow::Create(DPcCardSocket* aSocket, TPccdChnk aChnk, TPccdAccessSpeed aSpeed, TUint aFlag)
   1.900 +//
   1.901 +// Create a block of memory (IO, Common or Attribute memory).
   1.902 +//
   1.903 +	{
   1.904 +
   1.905 +	DPccdChunkBase *chunk=NULL;
   1.906 +	TBool chunkExists=EFalse;
   1.907 +	TInt r;
   1.908 +
   1.909 +	// See if requested window is actually part of a chunk already created
   1.910 +	TInt i;
   1.911 +	for (i=0;i<aSocket->iMemChunks.Count();i++)
   1.912 +		{
   1.913 +		if ((r=aSocket->iMemChunks[i]->AllocateWinCheck(aChnk,aFlag))==KErrNone)
   1.914 +			{
   1.915 +			chunk=aSocket->iMemChunks[i];
   1.916 +			chunkExists=ETrue;
   1.917 +			break;
   1.918 +			}
   1.919 +		if (r==KErrAccessDenied)
   1.920 +			return r;
   1.921 +		}
   1.922 +
   1.923 +	// If necesary, create a chunk
   1.924 +	if (!chunkExists)
   1.925 +		{
   1.926 +		// Create the memory chunk
   1.927 +		chunk=aSocket->NewPccdChunk(aChnk.iMemType);
   1.928 +		if (!chunk)
   1.929 +			return KErrNoMemory;
   1.930 +		TInt r=chunk->Create(aSocket, aChnk, aFlag);
   1.931 +		if (r==KErrNone)
   1.932 +			r=aSocket->iMemChunks.Append(chunk);
   1.933 +		if (r!=KErrNone)
   1.934 +			{
   1.935 +			delete chunk;
   1.936 +			return r;
   1.937 +			}
   1.938 +		}
   1.939 +	__KTRACE_OPT(KPBUS2,Kern::Printf("Skt:CreateMemWindowL-got chunk(existing-%d)",chunkExists));
   1.940 +
   1.941 +	// Create the memory window
   1.942 +	iOffset=aChnk.iMemBaseAddr-chunk->BaseAddr();
   1.943 +	iLen=aChnk.iMemLen;
   1.944 +	iAccessSpeed=aSpeed;
   1.945 +	iMemType=aChnk.iMemType;
   1.946 +	iWaitSig=(aFlag&KPccdRequestWait);
   1.947 +	iType=aFlag&(KPccdChunkShared|KPccdChunkPermanent|KPccdChunkSystemOwned); // Save flag settings
   1.948 +	chunk->AddWindow(this);
   1.949 +	__KTRACE_OPT(KPBUS2,Kern::Printf("Skt:CreateMemWindowL-created window"));
   1.950 +	return KErrNone;
   1.951 +	}
   1.952 +
   1.953 +EXPORT_C void RPccdWindow::Close()
   1.954 +	{
   1.955 +	if (iNext && iChunk)
   1.956 +		iChunk->RemoveWindow(this);
   1.957 +	}
   1.958 +
   1.959 +EXPORT_C TInt RPccdWindow::SetupChunkHw(TUint aFlag)
   1.960 +//
   1.961 +// Config h/w in preparation for accessing window. Flag is for platform dependant info.
   1.962 +//
   1.963 +	{
   1.964 +
   1.965 +	if (!iChunk)
   1.966 +		return(KErrNotReady);
   1.967 +	iChunk->SetupChunkHw(iAccessSpeed,iMemType,iWaitSig,aFlag);
   1.968 +//	iVcc->ResetInactivityTimer();
   1.969 +	return(KErrNone);
   1.970 +	}
   1.971 +
   1.972 +EXPORT_C TLinAddr RPccdWindow::LinearAddress()
   1.973 +//
   1.974 +// Return linear address of window
   1.975 +//
   1.976 +	{
   1.977 +	return iChunk->LinearAddress()+iOffset;
   1.978 +	}
   1.979 +
   1.980 +TBool RPccdWindow::Overlap(TUint32 anOffset,TUint aLen)
   1.981 +//
   1.982 +//
   1.983 +//
   1.984 +	{
   1.985 +	// If this window is sharable then it doesn't matter if they overlap or not.
   1.986 +	if (IsShareable())
   1.987 +		return(EFalse);
   1.988 +
   1.989 +	TUint32 winEnd=(anOffset+aLen-1);
   1.990 +	TUint32 thisEnd=(iOffset+iLen-1);
   1.991 +	if ((anOffset>=iOffset && anOffset<=thisEnd) ||
   1.992 +		(winEnd>=iOffset && winEnd<=thisEnd) )
   1.993 +		return(ETrue);
   1.994 +
   1.995 +	return(EFalse);
   1.996 +	}
   1.997 +