diff -r 578be2adaf3e -r 307f4279f433 Adaptation/GUID-43782364-0865-43D0-BC89-D63BA9912FB6.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Adaptation/GUID-43782364-0865-43D0-BC89-D63BA9912FB6.dita Fri Oct 15 14:32:18 2010 +0100 @@ -0,0 +1,174 @@ + + + + + +Basic ManagementThis document describes how device drivers should manage shared +chunks. +
Creation

A +shared chunk is created in kernel space. The user is given a handle to the +shared chunk to access it, and can pass the handle to other process or other +drivers. Chunks are represented by DChunk objects on the +kernel side and by RChunk on the user side.

A shared +chunk is created by using Kern::ChunkCreate(), which takes +a TChunkCreateInfo argument that sets the chunk properties.

Chunk +creation should be done in a critical section, created using NKern::ThreadEnterCS() and NKern::ThreadLeaveCS(). The size of the chunk should be in multiples of MMU pages, which can be +calculated using Kern::RoundToSize(n), where n is +the actual size that needs to be rounded.

/** + Create a transmit shared chunk of specified size. + + @param aChunkSize + size of the chunk to be created + + @return KErrNone on success, standard error code on failure + */ +TInt DExUartPhysicalChannel::CreateTxChunk(TUint aChunkSize) + { + ... + // Round up the transmit chunk size to the page size. + // Kern::RoundToPageSize() rounds up the argument to the size + // of a MMU page. The size of one MMU page can be found out by + // calling Kern::RoundToPageSize(1). + + size=Kern::RoundToPageSize(aChunkSize); + + // Thread must be in critical section + NKern::ThreadEnterCS(); + ... + // Create the chunk. Example is given in next code snippet + ... + // Commit the chunk. Example is given in following sections + ... + // Thread can leave the critical section + NKern::ThreadLeaveCS(); + } + +TInt DExUartPhysicalChannel::CreateTxChunk(TUint aChunkSize) + { + ... + NKern::ThreadLeaveCS(); // Enter the critical section + + // TChunkCreateInfo holds the parameters required to create a + // chunk and is used by Kern::ChunkCreate() + TChunkCreateInfo info; + + // ESharedKernelMultiple specifies that a chunk which may be opened by + // any number of user side processes + info.iType=TChunkCreateInfo::ESharedKernelMultiple; + info.iMaxSize= size; // Chunk size + + // This specifies the caching attributes for the chunk. It can + // be no caching or fully caching (TMappingAttributes enum + // type). If the MMU does not support the requested attributes, + // then a lesser cached attribute will be used. The actual + // value used is returned in aMapAttr of Kern::ChunkCreate() + info.iMapAttr=EMapAttrFullyBlocking; // No Caching, suitable for DMA + + // Set to true if the chunk is to own its committed memory. + // In this case all memory committed to the chunk will come + // from the system's free pool and will be returned there when + // the chunk is destroyed. If the chunk will be committed to + // physical address, then EFalse can be set. + info.iOwnsMemory=ETrue; // using RAM pages + + // As chunk destruction is asynchronous we can have + // a DFC, if required, specifying a callback function to get + // the chunk destroy notification exactly. This is used if any + // follow up cleaning has to be done after chunk destruction. + info.iDestroyedDfc=NULL; // No chunk destroy DFC. + + DChunk* chunk; + TUint32 mapAttr; + // Creates a chunk that can be shared between a user thread and a + // kernel thread. This will be the initial step for a shared + // chunk. Once created, the chunk owns a region of linear + // address space of the requested size. This region is empty + // (uncommitted) so before it can be used either RAM or I/O + // devices must be mapped into it. This is achieved with the + // Commit functions. + // Here iTxChunkKernAddr returns the linear address of the + // chunk created. + // + TInt r=Kern::ChunkCreate(info,chunk,iTxChunkKernAddr, mapAttr); + if (r!=KErrNone) + { + // Thread can leave the critical section + NKern::ThreadLeaveCS(); + return r; + } + ... + }
+
Destruction

To allow a chunk to be properly cleaned +up, a driver should close the chunk when it is no longer required. When a +chunk is closed, the reference count is decremented by one. The chunk gets +destroyed when the reference count becomes zero. Closing the chunk should +be done within a critical section.

The destruction of the chunk happens +asynchronously, and a notification of this can be requested. This is done +using a DFC, by initialising TChunkCreateInfo::iDestroyDfc() with +the DFC object.

/** + Close the transmit chunk, that was already created. This is + called while closing the logical channel + */ +void DExUartPhysicalChannel::CloseTxChunk() + { + // Thread must be in critical section + NKern::ThreadEnterCS(); + + // Atomically get pointer to our chunk and NULL the iChunk + // member. Nkern::SafeSwap() atomically replaces the word + // referenced by aPtr with aNewValue, here NULL. + // + DChunk* chunk = (DChunk*)NKern::SafeSwap(NULL,(TAny*&)iTxChunk); + + if (chunk) + { + // Close the chunk that was created. This should be + // done in a critical section. This function decrements + // a chunk's access count, and, if the count reaches + // zero, the chunk is scheduled for destruction. + // ChunkClose() has to be called the same number of times + // as chunk creation. A mismatch in this will result + // in either a memory leak or a panic. + // + Kern::ChunkClose(chunk); + } + // Thread can leave the critical section + NKern::ThreadLeaveCS(); + }
+
Mapping

Shared chunks must be mapped to memory, +which means that either RAM or an I/O device must be committed to a shared +chunk before it can be used. This maps the chunk to a certain address. The +memory can be physical contiguous RAM pages, an arbitrary set of RAM pages, +a physical region, or a physical region with a list of physical addresses. +The Kernel provides the following APIs for committing these types of memory:

// Commit RAM to a shared chunk. The memory pages to commit are +// obtained from the system's free pool +TInt Kern::ChunkCommit(DChunk *aChunk, TInt aOffset, TInt aSize); + +// Commit RAM to a shared chunk. The memory pages to commit are +// obtained from the system's free pool and will have physically +// contiguous addresses. Used when TChunkCreateInfo::iOwnsMemory +// is ETrue +TInt Kern::ChunkCommitContiguous(DChunk *aChunk, TInt aOffset, + TInt aSize, TUint32 &aPhysicalAddress); + +// Commit memory to a shared chunk. The physical region committed +// is that which starts at the supplied physical address. +// Typically, this region either represents memory mapped I/O, or +// RAM that was set aside for special use at system boot time. +// This is used when TChunkCreateInfo::iOwnsMemory is EFalse. +TInt Kern::ChunkCommitPhysical(DChunk *aChunk, TInt aOffset, + TInt aSize, TUint32 aPhysicalAddress); + +// Commit memory to a shared chunk. The physical region committed +// is determined by the list of physical addresses supplied to +// this function +TInt Kern::ChunkCommitPhysical(DChunk *aChunk, TInt aOffset, + TInt aSize, const TUint32 *aPhysicalAddressList); +
+
\ No newline at end of file