kernel/eka/drivers/pbus/mmc/mmccd_init.cpp
changeset 9 96e5fb8b040d
child 20 597aaf25e343
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/pbus/mmc/mmccd_init.cpp	Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,314 @@
+// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\drivers\pbus\mmc\mmccd_init.cpp
+// 
+//
+
+#include <drivers/mmccd_ifc.h>
+#include <drivers/pbusmedia.h>
+
+
+
+
+/**
+Starts the sequence of operations that creates the platform specific objects,
+registers the socket, and initialises the stack.
+
+The function is called in the Variant DLL's entry point code, i.e. when
+the kernel extension is initialised.
+
+Note that the Variant DLL is a kernel extension.
+
+@return KErrNone if creation and initialisation is successful;
+        one of the other system wide error codes otherwise.
+        
+@see TMMCardControllerInterface::NewStack()
+@see TMMCardControllerInterface::NewMediaChange()
+@see TMMCardControllerInterface::NewVcc()
+@see TMMCardControllerInterface::Init()
+@see TMMCardControllerInterface::IsMMCStack()
+@see TMMCardControllerInterface::MediaChangeID()
+@see TMMCardControllerInterface::VccID()
+*/	 
+EXPORT_C TInt TMMCardControllerInterface::Create()
+//
+// Allocate any resources. Only done once on kernel initialization so don't
+// worry about cleanup if it fails.
+//
+	{
+	TInt r=KErrNone;
+	__KTRACE_OPT(KPBUS1,Kern::Printf(">TMMCardControllerInterface::Create"));
+
+	// Create the password store (a single password store
+	//  is allocated for the use of all MMC stacks
+
+	TMMCPasswordStore* theMmcPasswordStore = (TMMCPasswordStore*)LocDrv::PasswordStore();
+	if(theMmcPasswordStore == NULL)
+		{
+		theMmcPasswordStore = new TMMCPasswordStore();
+		if(theMmcPasswordStore)
+			{
+			if((r = theMmcPasswordStore->Init()) == KErrNone)
+				r = LocDrv::RegisterPasswordStore(theMmcPasswordStore);					
+
+			if(r != KErrNone)
+				delete theMmcPasswordStore;
+			}
+		else
+			{
+			r = KErrNoMemory;
+			}
+		}
+
+	if(r!= KErrNone)
+		return r;
+
+	r = Init();
+	if (r != KErrNone)
+		return r;
+
+
+	SMediaDeviceInfo mdi;
+	TInt i;
+	for (i=0; i<KMaxPBusSockets && r==KErrNone; i++)
+		{
+		if (IsMMCSocket(i,mdi))
+			{
+			__KTRACE_OPT(KPBUS1,Kern::Printf("Socket %d is MMC card",i));
+
+			// Allocate a new socket
+			DMMCSocket* pS = NewSocket(i, theMmcPasswordStore);
+			if (!pS)
+				{
+				r=KErrNoMemory;
+				break;
+				}
+			TheSockets[i]=pS;
+
+			// Allocate a variant specific stack object via the interface
+			DMMCStack* pStack=NewStack(i, pS);
+			if (!pStack)
+				{
+				r=KErrNoMemory;
+				break;
+				}
+
+			pS->iStack=pStack;
+
+			TInt mcid=MediaChangeID(i);
+			__KTRACE_OPT(KPBUS1,Kern::Printf("Socket %d Media Change %d",i,mcid));
+			DMMCMediaChange* pM=(DMMCMediaChange*)TheMediaChanges[mcid];
+			if (!pM)
+				{
+				__KTRACE_OPT(KPBUS1,Kern::Printf("New Media Change"));
+				pM=NewMediaChange(mcid);
+				if (!pM)
+					{
+					r=KErrNoMemory;
+					break;
+					}
+				TheMediaChanges[mcid]=pM;
+				__KTRACE_OPT(KPBUS1,Kern::Printf("Media Change %d at %08x",mcid,pM));
+				r=pM->Create();
+				if (r!=KErrNone)
+					break;
+				}
+			else
+				{
+				__KTRACE_OPT(KPBUS1,Kern::Printf("Media Change %d already exists at %08x",mcid,pM));
+				++pM->iReplyCount;
+				}
+			TInt vcc=VccID(i);
+			__KTRACE_OPT(KPBUS1,Kern::Printf("Socket %d Vcc %d",i,vcc));
+			DMMCPsu* pV=(DMMCPsu*)TheVccs[vcc];
+			if (!pV)
+				{
+				__KTRACE_OPT(KPBUS1,Kern::Printf("New Vcc"));
+				pV=NewVcc(vcc,mcid);
+				if (!pV)
+					{
+					r=KErrNoMemory;
+					break;
+					}
+				TheVccs[vcc]=pV;
+				
+				// Assign Socket here such that iDFc can be obtained
+				pV->iSocket=pS;
+				
+				__KTRACE_OPT(KPBUS1,Kern::Printf("Vcc %d at %08x",vcc,pV));
+				r=pV->Create();
+				if (r!=KErrNone)
+					break;
+				}
+			else 
+				{
+				__KTRACE_OPT(KPBUS1,Kern::Printf("Vcc %d already exists at %08x, mcid=%d",vcc,pV,pV->iMediaChangeNum));
+// DISALLOW SHARED PSUs UNTIL SOMEONE NEEDS THEM
+//				if (pV->iMediaChangeNum!=mcid)
+//					{
+					r=KErrInUse;
+//					break;
+//					}
+				}
+			
+			DMMCPsu* pVCore=(DMMCPsu*)TheVccCores[vcc];
+			// N.B. Assume paired vcc & vccQ unit are numbered identically!
+			pVCore=NewVccCore(vcc,mcid);
+			if (pVCore)
+				{
+				TheVccCores[vcc]=pVCore;
+				__KTRACE_OPT(KPBUS1,Kern::Printf("VccCore %d at %08x",vcc,pVCore));
+				
+				// Assign Socket here such that iDFcQ can be obtained
+				pVCore->iSocket=pS;
+				
+				r=pVCore->Create();
+				if (r!=KErrNone)
+					break;
+				
+				// VccCore must issue sleep instead of power down 
+				pVCore->iPwrDownCheckFn = DMMCPsu::SleepCheck;				
+				}
+			//else do nothing doesn't matter if its not supported
+			
+			r=pS->Create(mdi.iDeviceName);
+			if (r!=KErrNone)
+				break;
+
+			pS->iMediaChangeNumber=mcid;
+			pS->iMediaChange=pM;
+			pS->iVcc=pV;
+			if (pVCore)
+				{
+				pS->iVccCore = pVCore;
+				}
+
+			r=pS->Init();
+			if (r!=KErrNone)		
+				break;
+
+			r = RegisterMediaDevices(i);
+			if(r != KErrNone)
+			   break;
+			
+			__KTRACE_OPT(KPBUS1,Kern::Printf("Socket %d Created OK",i));
+			}
+		else
+			__KTRACE_OPT(KPBUS1,Kern::Printf("Socket %d not MMC card",i));
+		}
+		
+	__KTRACE_OPT(KPBUS1,Kern::Printf("<TMMCardControllerInterface::Create, ret %d",r));
+	return r;
+	}
+
+EXPORT_C TInt TMMCardControllerInterface::RegisterMediaDevices(TInt aSocket)
+/**
+Registers the media devices for the specified socket.
+By default, All MMC derivatives register at least an MMC driver
+@internal
+*/
+	{
+	TInt err = KErrNone;
+	
+	SMediaDeviceInfo mdi;
+
+	if (IsMMCSocket(aSocket, mdi) == EFalse)
+		return(KErrNotSupported);
+		
+	DMMCSocket* pS = (DMMCSocket*) TheSockets[aSocket];
+	if(pS == NULL)
+		return(KErrNoMemory);
+
+	TMMCMachineInfo mi;
+	pS->iStack->MachineInfo(mi);
+	
+	// There may be more than one physical card slot for this socket/stack;
+	// if this is the case, then we have to create a separate DPBusPrimaryMedia 
+	// for each one. This is the only way to get the local media sub-system to iterate 
+	// through the installed set of media drivers repeatedly for each card slot
+	// (rather than once for the entire stack). We also need to share the number of 
+	// drives/partitions (SMediaDeviceInfo.iDriveCount) and the number of media 
+	// (SMediaDeviceInfo.iNumMedia) equally between the slots...
+	__ASSERT_ALWAYS(mdi.iDriveCount >= mi.iTotalSockets, DMMCSocket::Panic(DMMCSocket::EMMCInvalidNumberOfCardSlots) );
+	__ASSERT_ALWAYS(mdi.iNumMedia >= mi.iTotalSockets, DMMCSocket::Panic(DMMCSocket::EMMCInvalidNumberOfCardSlots) );
+
+	TInt physicalCardSlots = mi.iTotalSockets;
+	TInt drivesPerSlot = mdi.iDriveCount / physicalCardSlots;
+	TInt numMediaPerSlot = mdi.iNumMedia / physicalCardSlots;
+	TInt driveListIndex = 0;
+
+#if !defined(__WINS__)
+	DMMCStack::TDemandPagingInfo demandPagingInfo;
+	demandPagingInfo.iPagingDriveList = NULL;
+	demandPagingInfo.iDriveCount = 0;
+	TBool demandPagingSupported = 
+		pS->iStack->DemandPagingInfo(demandPagingInfo) == KErrNone ? (TBool)ETrue : (TBool)EFalse;
+
+#endif // __WINS__
+
+
+	for (TInt i=0; i<physicalCardSlots ; i++)	
+		{
+		DPBusPrimaryMedia* pMedia = new DPBusPrimaryMedia(pS);
+		if (pMedia == NULL)
+			return(KErrNoMemory);
+		// store the slot number in DPBusPrimaryMedia so that it can 
+		// subsequently be passed to the media driver.
+		pMedia->iSlotNumber = i;
+
+		err = LocDrv::RegisterMediaDevice(
+				mdi.iDevice,
+				drivesPerSlot,
+				mdi.iDriveList+driveListIndex,
+				pMedia,
+				numMediaPerSlot,
+				*mdi.iDeviceName);
+		if (err != KErrNone)
+			break;
+
+#if !defined(__WINS__)
+		if (demandPagingSupported && demandPagingInfo.iSlotNumber == i)
+			{
+			err = LocDrv::RegisterPagingDevice(
+				pMedia, 
+				demandPagingInfo.iPagingDriveList,
+				demandPagingInfo.iDriveCount,
+				demandPagingInfo.iPagingType,
+				demandPagingInfo.iReadShift,
+				demandPagingInfo.iNumPages);
+
+			// Ignore error if demand paging not supported by kernel
+			if (err == KErrNotSupported)
+				err = KErrNone;
+
+			if (err != KErrNone)
+				break;
+			}
+
+		if (mi.iFlags & TMMCMachineInfo::ESupportsDMA)
+			{
+			err = LocDrv::RegisterDmaDevice(pMedia,
+											KMMCardHighCapBlockSize, 
+											pS->MaxDataTransferLength(), 
+											pS->DmaAlignment());
+			if (err != KErrNone)
+				break;
+			}
+#endif // __WINS__
+
+		driveListIndex+= drivesPerSlot;
+		}
+	
+	return(err);
+	}