naviengine/navienginebsp/ne1_tb/test/pci/d_pci.cpp
branchRCL_3
changeset 49 a4ff6126ec76
equal deleted inserted replaced
45:be079f63985a 49:a4ff6126ec76
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This material, including documentation and any related computer
       
     5 * programs, is protected by copyright controlled by Nokia. All
       
     6 * rights are reserved. Copying, including reproducing, storing
       
     7 * adapting or translating, any or all of this material requires the
       
     8 * prior written consent of Nokia. This material also contains
       
     9 * confidential information which may not be disclosed to others
       
    10 * without the prior written consent of Nokia.
       
    11 *
       
    12 * Initial Contributors:
       
    13 * Nokia Corporation - initial contribution.
       
    14 *
       
    15 * Contributors:
       
    16 *
       
    17 * Description: Device-driver for naviEngine PCI testing 
       
    18 *
       
    19 */
       
    20 
       
    21 #include <kernel/kernel.h>
       
    22 #include <kernel/kern_priv.h>
       
    23 #include <pci.h>
       
    24 #include <naviengine.h>
       
    25 #include <kernel/cache.h>
       
    26 #include "allocator.h"
       
    27 #include "pci-ne.h"
       
    28 #include "pci_priv.h"
       
    29 #include <platform.h>
       
    30 #include "t_pci.h"
       
    31 #include "../../naviengine_assp/naviengine_pci.h"
       
    32 
       
    33 #define TEST(X) __NK_ASSERT_ALWAYS(X)
       
    34 #define TEST_KERRNONE(X) if((X) !=KErrNone) {\
       
    35 								  Kern::Printf("Assertion Failed X=%d", (X)); FAULT();}
       
    36 
       
    37 #define FUNC_LOG() __KTRACE_OPT(KPCI, Kern::Printf(__PRETTY_FUNCTION__))
       
    38 
       
    39  
       
    40 void TestAllocator();
       
    41 
       
    42 /**
       
    43 So that the test app can get notification
       
    44 when PCI DChunks' cleanup operation has run
       
    45 we will replace their cleanup object with this
       
    46 one, which will call the original object's destroy
       
    47 function as well completing a notification
       
    48 */
       
    49 class TPciCleanupWrapper : public TChunkCleanup
       
    50 	{
       
    51 public:
       
    52 
       
    53 	~TPciCleanupWrapper()
       
    54 		{
       
    55 		delete iOriginal;
       
    56 		Kern::DestroyClientRequest(iClientRequest);
       
    57 		iClient->Close(NULL);
       
    58 		}
       
    59 
       
    60 	static TPciCleanupWrapper* Create(TRequestStatus* aRequestStatus)
       
    61 		{
       
    62 		__KTRACE_OPT(KPCI, Kern::Printf("TPciCleanupWrapper::Create aRequestStatus=0x%08x", aRequestStatus));
       
    63 		TClientRequest* request = NULL;
       
    64 		TInt r = Kern::CreateClientRequest(request);
       
    65 		if(r != KErrNone)
       
    66 			{
       
    67 			__KTRACE_OPT(KPCI, Kern::Printf("TPciCleanupWrapper::Create Failed to create client request r=%d", r));
       
    68 			return NULL;
       
    69 			}
       
    70 
       
    71 		r = request->SetStatus(aRequestStatus);
       
    72 		if(r != KErrNone)
       
    73 			{
       
    74 			__KTRACE_OPT(KPCI, Kern::Printf("TPciCleanupWrapper::Create Failed to set status r=%d", r));
       
    75 			Kern::DestroyClientRequest(request);
       
    76 			return NULL;
       
    77 			}
       
    78 
       
    79 		return new TPciCleanupWrapper(request);
       
    80 		}
       
    81 
       
    82 	/**
       
    83 	Insert the cleanup object into aChunk, remembering
       
    84 	the original one
       
    85 
       
    86 	@param aChunk a chunk known to have TChunkCleanup derived cleanup object
       
    87 	*/
       
    88 	void Insert(DChunk* aChunk)
       
    89 		{
       
    90 		__KTRACE_OPT(KPCI, Kern::Printf("TPciCleanupWrapper::Insert aChunk=0x%08x", aChunk));
       
    91 		__NK_ASSERT_DEBUG(aChunk);
       
    92 		__KTRACE_OPT(KPCI, Kern::Printf("TPciCleanupWrapper replace 0x%08x with 0x%08x", aChunk->iDestroyedDfc, this));
       
    93 		iOriginal = static_cast<TChunkCleanup*>(aChunk->iDestroyedDfc);
       
    94 
       
    95 		__NK_ASSERT_DEBUG(iOriginal);
       
    96 		aChunk->iDestroyedDfc = this;
       
    97 		}
       
    98 
       
    99 	/**
       
   100 	Run the original object's destroy method
       
   101 	then notify client
       
   102 	*/
       
   103 	void Destroy()
       
   104 		{
       
   105 		__KTRACE_OPT(KPCI, Kern::Printf("TPciCleanupWrapper::Destroy\n"));
       
   106 		iOriginal->Destroy();
       
   107 
       
   108 		__NK_ASSERT_ALWAYS(iClientRequest->IsReady());
       
   109 		Kern::QueueRequestComplete(iClient, iClientRequest, KErrNone);
       
   110 		}
       
   111 
       
   112 private:
       
   113 	TPciCleanupWrapper(TClientRequest* aRequest)
       
   114 		:TChunkCleanup(), iOriginal(NULL), iClientRequest(aRequest), iClient(&Kern::CurrentThread())
       
   115 		{
       
   116 		__ASSERT_CRITICAL;
       
   117 		iClient->Open(); //don't allow thread object to be destroyed before we signal
       
   118 		}
       
   119 
       
   120 
       
   121 	TChunkCleanup* iOriginal;
       
   122 	TClientRequest* iClientRequest;
       
   123 	DThread* const iClient;
       
   124 	};
       
   125 
       
   126 
       
   127 
       
   128 
       
   129 //This information will come from the pci driver
       
   130 //if this code is ever made generic
       
   131 TPciTestInfo KTestInfo =
       
   132 	{
       
   133 	TPciDevice(0x1033, 0x35, 0),
       
   134 	TPciTestInfo::TAddrSpaceTest(0, 0x00351033, 0),
       
   135 	TPciTestInfo::TAddrSpaceTest(KPciBar0, 0, 0xFFF),
       
   136 	0,
       
   137 	TPciTestInfo::TAddrSpaceTest(0x34, 0x2EDF, 0),
       
   138 	TPciTestInfo::TAddrSpaceTest(0x20, 0, 0xF),
       
   139 	KNeBridgeNumberOfBars
       
   140 	};
       
   141 
       
   142 /**
       
   143 Class for a DChunk to remove a DPlatHwChunk chunk
       
   144 */
       
   145 class TPciPlatChunkCleanup : public TChunkCleanup
       
   146 	{
       
   147 public:
       
   148 	TPciPlatChunkCleanup(TInt aPciFunction, DPlatChunkHw* aPciPlatChunk);
       
   149 	virtual void Destroy();
       
   150 public:
       
   151 	TInt iPciFunction;
       
   152 	DPlatChunkHw* iPciChunk;
       
   153 	};
       
   154 
       
   155 TPciPlatChunkCleanup::TPciPlatChunkCleanup(TInt aPciFunction,  DPlatChunkHw* aPciPlatChunk)
       
   156 	: TChunkCleanup(), iPciFunction(aPciFunction), iPciChunk(aPciPlatChunk)
       
   157 	{
       
   158 	}
       
   159 
       
   160 void TPciPlatChunkCleanup::Destroy()
       
   161 	{	
       
   162 	__KTRACE_OPT(KPCI, Kern::Printf("SHAREDCHUNK ChunkDestroyed DFC\n"));
       
   163 	TInt r = Pci::RemoveChunk(iPciFunction, iPciChunk);
       
   164 	__NK_ASSERT_ALWAYS(r==KErrNone);
       
   165 	}
       
   166 
       
   167 /**
       
   168 Cleanup class to remove the mapping for an externally
       
   169 mapped chunk
       
   170 */
       
   171 class TPciMappedChunkCleanup : public TChunkCleanup
       
   172 	{
       
   173 public:
       
   174 	TPciMappedChunkCleanup (TInt aPciFunction,TUint32 aPhysicalAddress);
       
   175 	virtual void Destroy();
       
   176 public:
       
   177 	TInt iPciFunction;
       
   178 	TUint32 iPhysicalAddress;
       
   179 	};
       
   180 
       
   181 TPciMappedChunkCleanup::TPciMappedChunkCleanup(TInt aPciFunction,TUint32 aPhysicalAddress)
       
   182 	: TChunkCleanup(), iPciFunction(aPciFunction),iPhysicalAddress(aPhysicalAddress)
       
   183 	{	
       
   184 	}
       
   185 
       
   186 void TPciMappedChunkCleanup::Destroy()
       
   187 	{	
       
   188 	//remove mapping
       
   189 	TInt r = Pci::RemoveMapping(iPciFunction, iPhysicalAddress);
       
   190 	__NK_ASSERT_ALWAYS(r==KErrNone);	
       
   191 	__KTRACE_OPT(KPCI, Kern::Printf("MAPPING REMOVED ChunkDestroyed DFC\n"));
       
   192 	}
       
   193 
       
   194 class DPciTestChannel : public DLogicalChannelBase
       
   195 	{
       
   196 public:
       
   197 	DPciTestChannel();
       
   198 	virtual ~DPciTestChannel();
       
   199 	TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
       
   200 	virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
       
   201 
       
   202 private:
       
   203 	TInt OpenPciDChunk(TUint32& aPciAddr,TInt aPciChunkSize, TRequestStatus* aStatus);		
       
   204 	TInt OpenPciPlatHwChunk(TUint32& aPciAddr,TInt aPciChunkSize, TRequestStatus* aStatus);	
       
   205 	TInt OpenPciMappedChunk(TUint32& aPciAddr,TInt aPciChunkSize, TRequestStatus* aStatus);	 
       
   206 	TInt CreateSharedChunk(TInt aPciChunkSize, TUint32 aAttributes, DChunk*& aChunk, TLinAddr& aVirt, TPhysAddr& aPhysicalAddress);
       
   207 	TInt OpenPciWindowChunk();
       
   208 	void RunUnitTests();
       
   209 
       
   210 private:
       
   211 	const TPciTestInfo& iTestInfo;
       
   212 	TInt iFunction; ///< PCI function number this channel is associated with
       
   213 	};
       
   214 
       
   215 DPciTestChannel::DPciTestChannel()
       
   216 	: iTestInfo(KTestInfo), iFunction(-1)
       
   217 	{
       
   218 	FUNC_LOG();
       
   219 	}
       
   220 
       
   221 DPciTestChannel::~DPciTestChannel()
       
   222 	{
       
   223 	FUNC_LOG();
       
   224 	}
       
   225 
       
   226 TInt DPciTestChannel::DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
       
   227 	{
       
   228 	if(aInfo == NULL)
       
   229 		return KErrNone; //Not a device specific channel
       
   230 
       
   231 	TPciDevice dev;
       
   232 	TPckg<TPciDevice> devPckg(dev);
       
   233 	TInt r = Kern::ThreadDesRead(&Kern::CurrentThread(), aInfo, devPckg, 0, KChunkShiftBy0);
       
   234 	if(r != KErrNone)
       
   235 		return r;
       
   236 
       
   237 	NKern::ThreadEnterCS();
       
   238 	RArray<TInt> indicies;
       
   239 	r = Pci::Probe(indicies, dev.iVendorId, dev.iDeviceId);
       
   240 	
       
   241 	if((KErrNone == r) && (dev.iInstance < indicies.Count()))
       
   242 		{
       
   243 		iFunction = indicies[dev.iInstance];
       
   244 		}
       
   245 	else
       
   246 		{
       
   247 		r = KErrNotFound;
       
   248 		}
       
   249 	
       
   250 	indicies.Close();
       
   251 	NKern::ThreadLeaveCS();
       
   252 	return r;
       
   253 	}
       
   254 
       
   255 TInt DPciTestChannel::Request(TInt aFunction, TAny* a1, TAny* a2)
       
   256 	{
       
   257 	switch (aFunction)
       
   258 		{
       
   259 		case EGetTestInfo:
       
   260 			{
       
   261 			TDes8& dest(*(TDes8*)a1);
       
   262 			TPckgC<TPciTestInfo> info(iTestInfo);
       
   263 			Kern::KUDesPut(dest, info);
       
   264 			return KErrNone;
       
   265 			}
       
   266 		case EAccessConfigSpace:
       
   267 			{
       
   268 			TPckgBuf<TUserConfigSpace> pckg;
       
   269 			Kern::KUDesGet(pckg, *reinterpret_cast<TDes8*>(a1));
       
   270 		
       
   271 			TAddrSpace* configSpace = Pci::GetConfigSpace(iFunction);
       
   272 			if(configSpace == NULL)
       
   273 				{
       
   274 				Kern::PanicCurrentThread(KPciTest, KErrGeneral);
       
   275 				return KErrGeneral;
       
   276 				}
       
   277 			return pckg().KRun(*configSpace);
       
   278 			}
       
   279 		case EAccessMemorySpace:
       
   280 			{
       
   281 			TPckgBuf<TUserMemorySpace> pckg;
       
   282 			Kern::KUDesGet(pckg, *reinterpret_cast<TDes8*>(a1));
       
   283 
       
   284 			TAddrSpace* memSpace = Pci::GetMemorySpace(iFunction, pckg().BarIndex());
       
   285 			if(memSpace == NULL)
       
   286 				{
       
   287 				Kern::PanicCurrentThread(KPciTest, KErrGeneral);
       
   288 				return KErrGeneral;
       
   289 				}
       
   290 			return pckg().KRun(*memSpace);
       
   291 			}
       
   292 		case EOpenPciWindowChunk:
       
   293 			{				
       
   294 			TInt rHandle = 0;				
       
   295 			rHandle = OpenPciWindowChunk();		
       
   296 			return rHandle;			
       
   297 			}
       
   298 		case EOpenPciDChunk: //Fall-through
       
   299 		case EOpenPciPlatHwChunk:
       
   300 		case EOpenPciMappedChunk:
       
   301 			{				
       
   302 				TPckgBuf<TPciChunkCreateInfo> pckg;				
       
   303 				Kern::KUDesGet(pckg, *reinterpret_cast<TDes8*>(a1));
       
   304 
       
   305 				TUint32 pciAddr;				
       
   306 				TInt rHandle = 0;				
       
   307 				switch (aFunction)
       
   308 					{
       
   309 				case EOpenPciDChunk:
       
   310 						{						
       
   311 						rHandle = OpenPciDChunk(pciAddr, pckg().iSize, pckg().iStatus);						
       
   312 						break;
       
   313 						}
       
   314 				case EOpenPciPlatHwChunk:
       
   315 						{						
       
   316 						rHandle = OpenPciPlatHwChunk(pciAddr, pckg().iSize, pckg().iStatus);				
       
   317 						break;
       
   318 						}
       
   319 				case EOpenPciMappedChunk:
       
   320 						{
       
   321 						rHandle = OpenPciMappedChunk(pciAddr, pckg().iSize, pckg().iStatus);					
       
   322 						break;
       
   323 						}
       
   324 				default:
       
   325 						{
       
   326 						FAULT();
       
   327 						}
       
   328 					}
       
   329 				//write back PCI address to user
       
   330 				umemput(pckg().iPciAddress,&pciAddr,sizeof(pciAddr));				
       
   331 				return rHandle;			
       
   332 			}
       
   333 		case ERunUnitTests:
       
   334 			{					
       
   335 			RunUnitTests();					
       
   336 			return KErrNone;		
       
   337 			}
       
   338 		default:
       
   339 			return KErrNotSupported;
       
   340 		}
       
   341 	}
       
   342 
       
   343 /**
       
   344 This function runs tests for the address allocator
       
   345 */
       
   346 void DPciTestChannel::RunUnitTests()
       
   347 {
       
   348 	// Enter critical section 
       
   349    	NKern::ThreadEnterCS();		
       
   350 	
       
   351 	TestAllocator();
       
   352 
       
   353  	// Finished
       
   354 	NKern::ThreadLeaveCS();
       
   355 }
       
   356 
       
   357 
       
   358 /**
       
   359 This function creates and opens a PCI DChunk and returns the PCI addresss
       
   360 @param aPciAddr on return contains the pci address
       
   361 @param aPciChunkSize contains the size of the PCI DChunk which is to be created
       
   362 */
       
   363 TInt DPciTestChannel::OpenPciDChunk(TUint32& aPciAddr,TInt aPciChunkSize, TRequestStatus* aStatus)
       
   364 {
       
   365 	//Chunk Attributes 
       
   366 	TChunkCreateInfo aInfo;
       
   367 	aInfo.iType = TChunkCreateInfo::ESharedKernelMultiple;
       
   368 	aInfo.iMapAttr = EMapAttrSupRw|EMapAttrFullyBlocking;
       
   369 	aInfo.iOwnsMemory = EFalse; // We'll be using our own devices memory
       
   370 	
       
   371 	DChunk* pciChunk;
       
   372 	pciChunk=NULL;	
       
   373 
       
   374     // Enter critical section 
       
   375 	NKern::ThreadEnterCS();
       
   376 	
       
   377 	//Create DChunk
       
   378 	TInt r = Pci::CreateChunk(iFunction, pciChunk, aInfo,0,aPciChunkSize,aPciAddr);
       
   379 	if(r!=KErrNone)
       
   380 	{
       
   381 		// Failed to create DChunk	
       
   382 		__KTRACE_OPT(KPCI,Kern::Printf("Failed to create DChunk: Error code is=%d", r) );
       
   383 		NKern::ThreadLeaveCS(); // Finished
       
   384 		return r;		
       
   385 	}
       
   386 	else
       
   387 	{
       
   388 		TInt rHandle = KErrGeneral;
       
   389 		if(aStatus)
       
   390 			{
       
   391 			TPciCleanupWrapper* wrapper = TPciCleanupWrapper::Create(aStatus);
       
   392 			if(wrapper == NULL)
       
   393 				{
       
   394 				__KTRACE_OPT(KPCI,Kern::Printf("Creation of TPciCleanupWrapper failed"));
       
   395 				goto End;
       
   396 				}
       
   397 			wrapper->Insert(pciChunk);
       
   398 			}
       
   399 
       
   400 		__KTRACE_OPT(KPCI,Kern::Printf("Created DChunk: PCI_ADDRESS=0x%08x",aPciAddr));
       
   401 		rHandle = Kern::MakeHandleAndOpen(NULL, pciChunk);//Get DChunk handle	
       
   402 
       
   403 End:
       
   404 		pciChunk->Close(NULL);		// Close DChunk		
       
   405 		NKern::ThreadLeaveCS(); 	// Finished
       
   406 		return rHandle;
       
   407 	}
       
   408 }
       
   409 
       
   410 /**
       
   411 This function creates and opens a PCI DPlatChunk and returns the PCI addresss.
       
   412 A DPlatChunk is intially created and then a DChunk is set to point to the same 
       
   413 memory as the DPlatChunk.This is done so that it can be accessed on the user side. 
       
   414 @param aPciAddr on return contains the pci address
       
   415 @param aPciChunkSize contains the size of the PCI PlatHwChunk which is to be created
       
   416 */
       
   417 TInt DPciTestChannel::OpenPciPlatHwChunk(TUint32& aPciAddr,TInt aPciChunkSize, TRequestStatus* aStatus)
       
   418 {
       
   419 	TUint32 pciPhysicalAddr;
       
   420 	TUint32 pciChunkMapAttr;	
       
   421 	TLinAddr pciChunkKernelAddr;
       
   422 
       
   423 	DPlatChunkHw* pciPlatChunk;
       
   424 	pciPlatChunk=NULL;	
       
   425 
       
   426     // Enter critical section 
       
   427 	NKern::ThreadEnterCS();
       
   428 	
       
   429 	//Create DPlatChunkHw
       
   430 	TInt r = Pci::CreateChunk(iFunction,pciPlatChunk,aPciChunkSize,(EMapAttrSupRw|EMapAttrFullyBlocking),aPciAddr);
       
   431 	if(r!=KErrNone)
       
   432 	{
       
   433 		// Failed to create DPlatChunkHw	
       
   434 		__KTRACE_OPT(KPCI,Kern::Printf("Failed to create DPlatChunkHw chunk: Error code is=%d", r));
       
   435 		NKern::ThreadLeaveCS(); // Finished
       
   436 		return r;	
       
   437 	}
       
   438 
       
   439 	//Get physical addresss
       
   440 	pciPhysicalAddr	= pciPlatChunk->PhysicalAddress();
       
   441 	
       
   442 	// Create DChunk cleanup object
       
   443 	TPciPlatChunkCleanup* cleanup = new TPciPlatChunkCleanup(iFunction, pciPlatChunk);
       
   444 	if(!cleanup)
       
   445     {
       
   446 		pciPlatChunk->Close(NULL); //close pciPlatChunk
       
   447 		NKern::ThreadLeaveCS();
       
   448 		return KErrNoMemory;
       
   449     }
       
   450 	
       
   451 	//Chunk Attributes  for DChunk
       
   452 	TChunkCreateInfo chunkinfo;
       
   453 	chunkinfo.iType         = TChunkCreateInfo::ESharedKernelMultiple;    
       
   454 	chunkinfo.iMaxSize      = 0x4000;
       
   455 	chunkinfo.iMapAttr      = EMapAttrSupRw|EMapAttrFullyBlocking; // No caching
       
   456 	chunkinfo.iOwnsMemory   = EFalse; // Use memory from system's free pool
       
   457 	chunkinfo.iDestroyedDfc = cleanup;
       
   458 
       
   459 	DChunk* pciDChunk;
       
   460   
       
   461 	//Create DChunk
       
   462 	r = Kern::ChunkCreate(chunkinfo, pciDChunk, pciChunkKernelAddr, pciChunkMapAttr);
       
   463 	if(r!=KErrNone)
       
   464     {
       
   465 		pciPlatChunk->Close(NULL); //close pciPlatChunk
       
   466 		delete cleanup;
       
   467 		NKern::ThreadLeaveCS();
       
   468 		return r;
       
   469 	}
       
   470 
       
   471 	pciPlatChunk=NULL; // pciDChunk now owns chunk        	
       
   472 
       
   473 	if(aStatus)
       
   474 		{
       
   475 		TPciCleanupWrapper* wrapper = TPciCleanupWrapper::Create(aStatus);
       
   476 		if(wrapper == NULL)
       
   477 			{
       
   478 			pciDChunk->Close(NULL);	// Close pciDChunk	
       
   479 			NKern::ThreadLeaveCS(); // Finished
       
   480 			return KErrGeneral;
       
   481 			}
       
   482 		wrapper->Insert(pciDChunk);
       
   483 		}
       
   484 
       
   485 	//Commit memory to a DChunk using DPlatChunkHw physical address
       
   486 	r = Kern::ChunkCommitPhysical(pciDChunk,0,aPciChunkSize,pciPhysicalAddr);
       
   487 	if(r!=KErrNone)
       
   488 	{
       
   489 		// Failed to commit memory
       
   490 		Kern::Printf("Commit failed: Error code is=%d", r);
       
   491 		__KTRACE_OPT(KPCI,Kern::Printf("Commit failed: Error code is=%d", r));
       
   492 
       
   493 		// Close chunk, which will then get deleted at some point
       
   494 		Kern::ChunkClose(pciDChunk);
       
   495 		NKern::ThreadLeaveCS();
       
   496 		return r;
       
   497 	}	
       
   498 	
       
   499 	//Close pciPlatChunk using pciDChunk as pciDChunk now owns it
       
   500 	const TInt rHandle = Kern::MakeHandleAndOpen(NULL, pciDChunk); //Get DChunk handle
       
   501 	pciDChunk->Close(NULL);	// Close pciDChunk	
       
   502 	NKern::ThreadLeaveCS(); // Finished
       
   503 	return rHandle;   	
       
   504 }
       
   505 
       
   506 /**
       
   507 This function creates and opens a PCI mapped DChunk and returns the PCI addresss
       
   508 @param aPciAddr on return contains the pci address
       
   509 @param aPciChunkSize contains the size of the PCI DChunk which is to be created
       
   510 */
       
   511 TInt DPciTestChannel::OpenPciMappedChunk(TUint32& aPciAddr,TInt aPciChunkSize, TRequestStatus* aStatus)
       
   512 {
       
   513 	TLinAddr virt=NULL;
       
   514 	TPhysAddr physicalAddress=NULL;
       
   515 	DChunk* pciChunk=NULL;
       
   516 	TUint32 pciAttributes=EMapAttrSupRw|EMapAttrFullyBlocking;
       
   517 
       
   518 	// Enter critical section 
       
   519 	NKern::ThreadEnterCS();	
       
   520 
       
   521 	//create DChunk
       
   522 	TInt r = CreateSharedChunk(aPciChunkSize, pciAttributes, pciChunk, virt, physicalAddress);
       
   523 	if(r!=KErrNone)
       
   524 	{
       
   525 	__KTRACE_OPT(KPCI,Kern::Printf("Create shared Chunk failed: Error code is=%d", r));
       
   526 	return r;
       
   527 	}
       
   528 	
       
   529 	__NK_ASSERT_ALWAYS(pciChunk);
       
   530 
       
   531 	//create mapping
       
   532 	r=Pci::CreateMapping(iFunction, physicalAddress, aPciChunkSize, aPciAddr);
       
   533 	if(r!=KErrNone)
       
   534 	{
       
   535 	pciChunk->Close(NULL);
       
   536 	__KTRACE_OPT(KPCI,Kern::Printf("Create mapping failed: Error code is=%d", r));
       
   537 	return r;
       
   538 	}	
       
   539 
       
   540 
       
   541 	// Create DChunk cleanup object
       
   542 	TPciMappedChunkCleanup* cleanup = new TPciMappedChunkCleanup(iFunction, physicalAddress);
       
   543 	if(!cleanup)
       
   544 		{
       
   545 			pciChunk->Close(NULL);
       
   546 			NKern::ThreadLeaveCS();
       
   547 			return KErrNoMemory;
       
   548 		}
       
   549 
       
   550 	//must add the cleanup dfc to the chunk after creation
       
   551 	//since the cleanup parameters aren't known
       
   552 	//till after creating it and allocating memory to it
       
   553 	pciChunk->iDestroyedDfc = cleanup;
       
   554 
       
   555 	if(aStatus)
       
   556 		{
       
   557 		TPciCleanupWrapper* wrapper = TPciCleanupWrapper::Create(aStatus);
       
   558 		if(wrapper == NULL)
       
   559 			{
       
   560 			pciChunk->Close(NULL);	// Close pciDChunk	
       
   561 			NKern::ThreadLeaveCS();
       
   562 			return KErrGeneral;
       
   563 			}
       
   564 		wrapper->Insert(pciChunk);
       
   565 		}
       
   566 	
       
   567 	//Get DChunk handle
       
   568 	const TInt rHandle = Kern::MakeHandleAndOpen(NULL, pciChunk);	
       
   569 	
       
   570 	// Close DChunk		
       
   571 	pciChunk->Close(NULL);		    
       
   572 	
       
   573 	// Finished
       
   574 	NKern::ThreadLeaveCS(); 	
       
   575 	return rHandle;
       
   576 }
       
   577 
       
   578 /**
       
   579 This function creates and opens a PCI Window Chunk and returns the PCI Window addresss
       
   580 @param aPciChunkSize contains the size of the PCI Window DChunk which is to be created
       
   581 */
       
   582 TInt DPciTestChannel::OpenPciWindowChunk()
       
   583 {
       
   584 	TUint32 pciChunkMapAttr;	
       
   585 	TLinAddr pciChunkKernelAddr=NULL;
       
   586 	DChunk* pciWindowChunk=NULL;	
       
   587 
       
   588 	//Chunk Attributes  for DChunk
       
   589 	TChunkCreateInfo chunkinfo;
       
   590 	chunkinfo.iType         = TChunkCreateInfo::ESharedKernelMultiple;    
       
   591 	chunkinfo.iMaxSize      = 0x2000;
       
   592 	chunkinfo.iMapAttr      = EMapAttrSupRw|EMapAttrFullyBlocking; // No caching
       
   593 	chunkinfo.iOwnsMemory   = EFalse; // Use memory from system's free pool
       
   594 
       
   595 	 // Enter critical section 
       
   596 	NKern::ThreadEnterCS();
       
   597 	
       
   598 	//Create shared chunk for PCI window
       
   599 	TInt r = Kern::ChunkCreate(chunkinfo, pciWindowChunk, pciChunkKernelAddr, pciChunkMapAttr);
       
   600 	if(r!=KErrNone)
       
   601     {
       
   602 		// Failed to create DChunk	
       
   603 		__KTRACE_OPT(KPCI,Kern::Printf("Failed to create DChunk: Error code is=%d", r) );		
       
   604 		NKern::ThreadLeaveCS();
       
   605 		return r;
       
   606 	}
       
   607 
       
   608 	//This address is PSL specific. This will have to be changed
       
   609 	//if d_pci.cpp is ever made generic
       
   610 	TUint32 pciPhysicalAddr = KHwUSBHPhys; // Internal PCI window address
       
   611 
       
   612 	//Commit memory to a DChunk using  Internal PCI window address
       
   613 	r = Kern::ChunkCommitPhysical(pciWindowChunk,0,KHwUSBHInternalPciWindowSize, pciPhysicalAddr);
       
   614 	if(r!=KErrNone)
       
   615 	{
       
   616 		// Failed to commit memory
       
   617 		Kern::Printf("Commit failed: Error code is=%d", r);
       
   618 		__KTRACE_OPT(KPCI,Kern::Printf("Commit failed: Error code is=%d", r));
       
   619 
       
   620 		// Close chunk, which will then get deleted at some point
       
   621 		Kern::ChunkClose(pciWindowChunk);
       
   622 		NKern::ThreadLeaveCS();
       
   623 		return r;
       
   624 	}		
       
   625 
       
   626 	//Close pciPlatChunk using pciDChunk as pciDChunk now owns it
       
   627 	const TInt rHandle = Kern::MakeHandleAndOpen(NULL, pciWindowChunk); //Get PCI Window DChunk handle
       
   628 	pciWindowChunk->Close(NULL);	// Close pci window chunk	
       
   629 	NKern::ThreadLeaveCS(); // Finished
       
   630 	return rHandle;   	
       
   631 }
       
   632 
       
   633 /**
       
   634 This function creates and opens a shared chunk. The chunk is then commited to a contiguous memory
       
   635 @param aPciChunkSize contains the size of the PCI DChunk which is to be created
       
   636 @param aAttributes  on return, this is set to the mmu mapping attributes used for the chunk
       
   637 @param aChunk on return, a reference to the shared chunk
       
   638 @param aVirt on return, this is set to the virtual address shared chunk
       
   639 @param aPhysicalAddress on return, this is set to the physical address of the first page of memory
       
   640 	   which was committed.
       
   641 */
       
   642 TInt DPciTestChannel::CreateSharedChunk(TInt aPciChunkSize, TUint32 aAttributes, DChunk*& aChunk, TLinAddr& aVirt, TPhysAddr& aPhysicalAddress)
       
   643 {
       
   644 	__NK_ASSERT_DEBUG(aChunk==NULL);
       
   645 	aPciChunkSize = Kern::RoundToPageSize(aPciChunkSize);
       
   646 	DChunk* pC=NULL;
       
   647 
       
   648 	// Enter critical section 
       
   649 	NKern::ThreadEnterCS();
       
   650 
       
   651 	//Chunk Attributes  for DChunk
       
   652 	TChunkCreateInfo info;
       
   653 	info.iType=TChunkCreateInfo::ESharedKernelSingle;
       
   654 	info.iMaxSize=aPciChunkSize;
       
   655 	info.iMapAttr=aAttributes;
       
   656 	info.iOwnsMemory=ETrue;
       
   657 
       
   658 	//Create DChunk
       
   659 	TInt r=Kern::ChunkCreate(info, pC, aVirt, aAttributes);
       
   660 	if(r!=KErrNone)
       
   661 		{
       
   662 		NKern::ThreadLeaveCS();
       
   663 		return r;
       
   664 		}
       
   665 	//Commit DChunk to Contiguous memory
       
   666 	r = Kern::ChunkCommitContiguous(pC, 0, aPciChunkSize, aPhysicalAddress);
       
   667 	if(r==KErrNone)
       
   668 		{
       
   669 			aChunk=pC;		
       
   670 		}
       
   671 	else
       
   672 		{
       
   673 		Kern::ChunkClose(pC);
       
   674 		__KTRACE_OPT(KPCI,Kern::Printf("Commit DChunk to Contiguous memory Failed : Error code is=%d",r));
       
   675 		return r;
       
   676 		}
       
   677 
       
   678 	NKern::ThreadLeaveCS(); // Finished
       
   679 	__KTRACE_OPT(KPCI, Kern::Printf("Created SC: size=0x%08x, virtual= 0x%08x, phys=0x%08x", aPciChunkSize, aVirt, aPhysicalAddress));	
       
   680 	return r;
       
   681 }
       
   682 
       
   683 class DPciDevice : public DLogicalDevice
       
   684 	{
       
   685 public:
       
   686 	DPciDevice();
       
   687 	~DPciDevice();
       
   688 	TInt Install();
       
   689 	void GetCaps(TDes8& aDes) const;
       
   690 	TInt Create(DLogicalChannelBase*& aChannel);
       
   691 	};
       
   692 
       
   693 DPciDevice::DPciDevice()
       
   694 	{
       
   695 	FUNC_LOG();
       
   696 	}
       
   697 
       
   698 DPciDevice::~DPciDevice()
       
   699 	{
       
   700 	FUNC_LOG();
       
   701 	}
       
   702 
       
   703 TInt DPciDevice::Install()
       
   704 	{
       
   705 	return SetName(&KPciLddFactory);
       
   706 	}
       
   707 
       
   708 void DPciDevice::GetCaps(TDes8&) const
       
   709 	{
       
   710 	}
       
   711 
       
   712 TInt DPciDevice::Create(DLogicalChannelBase*& aChannel)
       
   713 	{
       
   714 	aChannel = new DPciTestChannel;
       
   715 	return aChannel ? KErrNone : KErrNoMemory;
       
   716 	}
       
   717 
       
   718 /****************************************
       
   719 TUserPciSpace
       
   720 */
       
   721 
       
   722 /**
       
   723 Decides what action to run based on contents of class
       
   724 */
       
   725 TUint TUserPciSpace::KRun(TAddrSpace& aAddrSp)
       
   726 	{
       
   727 
       
   728 	//this could be reworked as a function pointer
       
   729 	//table, but this might be clearer
       
   730 	switch(iBitWidth)
       
   731 		{
       
   732 	case 8:
       
   733 			{
       
   734 			switch(iOperation)
       
   735 				{
       
   736 			case ERead:
       
   737 					{
       
   738 					return aAddrSp.Read8(iOffset);
       
   739 					}
       
   740 			case EWrite:
       
   741 					{
       
   742 					aAddrSp.Write8(iOffset, iWriteValue);
       
   743 					return KErrNone;
       
   744 					}
       
   745 			case EModify:
       
   746 					{
       
   747 					aAddrSp.Modify8(iOffset, iClearMask, iSetMask);
       
   748 					return KErrNone;
       
   749 					}
       
   750 			default:
       
   751 					{
       
   752 					Kern::PanicCurrentThread(KPciTest, KErrNotReady);
       
   753 					}
       
   754 				}
       
   755 			}
       
   756 	case 16:
       
   757 			{
       
   758 			switch(iOperation)
       
   759 				{
       
   760 			case ERead:
       
   761 					{
       
   762 					return aAddrSp.Read16(iOffset);
       
   763 					}
       
   764 			case EWrite:
       
   765 					{
       
   766 					aAddrSp.Write16(iOffset, iWriteValue);
       
   767 					return KErrNone;
       
   768 					}
       
   769 			case EModify:
       
   770 					{
       
   771 					aAddrSp.Modify16(iOffset, iClearMask, iSetMask);
       
   772 					return KErrNone;
       
   773 					}
       
   774 			default:
       
   775 					{
       
   776 					Kern::PanicCurrentThread(KPciTest, KErrNotReady);
       
   777 					}
       
   778 				}
       
   779 			}
       
   780 	case 32:
       
   781 			{
       
   782 			switch(iOperation)
       
   783 				{
       
   784 			case ERead:
       
   785 					{
       
   786 					return aAddrSp.Read32(iOffset);
       
   787 					}
       
   788 			case EWrite:
       
   789 					{
       
   790 					aAddrSp.Write32(iOffset, iWriteValue);
       
   791 					return KErrNone;
       
   792 					}
       
   793 			case EModify:
       
   794 					{
       
   795 					aAddrSp.Modify32(iOffset, iClearMask, iSetMask);
       
   796 					return KErrNone;
       
   797 					}
       
   798 			default:
       
   799 					{
       
   800 					Kern::PanicCurrentThread(KPciTest, KErrNotReady);
       
   801 					}
       
   802 				}
       
   803 			}
       
   804 	default:
       
   805 			{
       
   806 			Kern::PanicCurrentThread(KPciTest, KErrArgument);
       
   807 			}
       
   808 			
       
   809 		}
       
   810 
       
   811 	//unreachable return
       
   812 	return KMaxTUint;
       
   813 	}
       
   814 
       
   815 //stub implementation for kernel side
       
   816 TUint TUserConfigSpace::Call()
       
   817 		{
       
   818 		FAULT();
       
   819 		return 0;
       
   820 		} 
       
   821 
       
   822 TUserPciSpace* TUserConfigSpace::Clone() const
       
   823 		{
       
   824 		FAULT();
       
   825 		return 0;
       
   826 		} 
       
   827 
       
   828 //stub implementation for kernel side
       
   829 TUint TUserMemorySpace::Call()
       
   830 		{
       
   831 		FAULT();
       
   832 		return 0;
       
   833 		} 
       
   834 
       
   835 TUserPciSpace* TUserMemorySpace::Clone() const
       
   836 		{
       
   837 		FAULT();
       
   838 		return 0;
       
   839 		} 
       
   840 
       
   841 void TestAllocator()
       
   842 	{
       
   843 	__KTRACE_OPT(KPCI, Kern::Printf("Testing address allocator"));
       
   844 	TAddressAllocator allocator(0x80000000); //2 GB
       
   845 	TLinAddr rcvdAddr=NULL;
       
   846 	TEST_KERRNONE(allocator.Allocate(rcvdAddr,0x10) );
       
   847 	TEST(0x0 ==rcvdAddr);
       
   848 	TEST_KERRNONE(allocator.Allocate(rcvdAddr,0x100) );
       
   849 	TEST(0x100 ==rcvdAddr);
       
   850 	TEST_KERRNONE(allocator.Allocate(rcvdAddr,0x10) );
       
   851 	TEST(0x10 ==rcvdAddr);
       
   852 	TEST_KERRNONE(allocator.Allocate(rcvdAddr,0x10) );
       
   853 	TEST(0x20 ==rcvdAddr);
       
   854 	//test deallocating
       
   855 	TEST_KERRNONE(allocator.DeAllocate(0x0));
       
   856 	TEST_KERRNONE(allocator.Allocate(rcvdAddr,0x10) );
       
   857 	TEST(0x000 ==rcvdAddr);
       
   858 
       
   859 	TEST_KERRNONE(allocator.DeAllocate(0x100));
       
   860 	TEST_KERRNONE(allocator.Allocate(rcvdAddr,0x100) );
       
   861 	TEST(0x100 ==rcvdAddr);
       
   862 
       
   863 	TEST_KERRNONE(allocator.DeAllocate(0x10));
       
   864 	TEST_KERRNONE(allocator.Allocate(rcvdAddr,0x10) );
       
   865 	TEST(0x10 ==rcvdAddr);
       
   866 
       
   867 	TEST_KERRNONE(allocator.DeAllocate(0x20));
       
   868 	TEST_KERRNONE(allocator.Allocate(rcvdAddr,0x20) );
       
   869 	TEST(0x20 ==rcvdAddr);
       
   870 
       
   871 	TEST(allocator.DeAllocate(0x40)==KErrNotFound);
       
   872 	TEST_KERRNONE(allocator.DeAllocate(0x100));
       
   873 	TEST_KERRNONE(allocator.DeAllocate(0x20));
       
   874 	TEST_KERRNONE(allocator.DeAllocate(0x0));
       
   875 	TEST_KERRNONE(allocator.DeAllocate(0x10));
       
   876 	}
       
   877 
       
   878 
       
   879 DECLARE_STANDARD_LDD()
       
   880 	{
       
   881 	return new DPciDevice;
       
   882 	}