|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE concept |
|
11 PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd"> |
|
12 <concept id="GUID-A87D9280-B61A-49BA-A9AF-178DB9BAECBC" xml:lang="en"><title>Reading and Writing</title><shortdesc>This document describes how device drivers should open, read from |
|
13 and write to shared chunks.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
14 <p>Both user-side code and drivers can read and write to shared chunks. Once |
|
15 the chunk is created, opened, and memory committed to it, data can be written |
|
16 and read to the shared chunk using the base address. </p> |
|
17 <section id="GUID-4CF7C47A-24D2-4D6D-B577-F0351178CA38"><title>Opening</title> <p>If a shared chunk has already been created |
|
18 by a driver, then another driver can access that shared chunk through its |
|
19 handle by using one of the following functions: </p> <codeblock id="GUID-EB073A6D-5DC3-5572-BD7C-E96F63BB8DCF" xml:space="preserve">DChunk* Kern::OpenSharedChunk(DThread* aThread, TInt aChunkHandle, |
|
20 TBool aWrite); |
|
21 |
|
22 DChunk* Kern::OpenSharedChunk(DThread *aThread, |
|
23 const TAny *aAddress, TBool aWrite, |
|
24 TInt &aOffset); |
|
25 </codeblock></section> |
|
26 <section id="GUID-95D166D2-C6BE-45F5-84E7-6F5ACB1BFA38"><title>User-side access</title> <p> <xref href="GUID-326A2F4D-0E99-31C0-A35D-E8BF45913F07.dita"><apiname>RChunk</apiname></xref> is |
|
27 the user side representation of a shared chunk. The user gets a shared chunk |
|
28 handle from a driver, and initialises the <codeph>RChunk</codeph> object with |
|
29 it using <codeph>RChunk::SetHandle(TInt aHandle)</codeph>. </p> <p>The user |
|
30 can now obtain the base address of the chunk by calling <xref href="GUID-326A2F4D-0E99-31C0-A35D-E8BF45913F07.dita#GUID-326A2F4D-0E99-31C0-A35D-E8BF45913F07/GUID-D19E68E8-3C5F-3F97-80F2-B2F80A814A80"><apiname>RChunk::Base()</apiname></xref>. |
|
31 Data can be read or written to this memory location, in same way as any other |
|
32 memory. </p> <codeblock id="GUID-E0F57FBB-1F43-564F-8350-A49B6AFEE3F1" xml:space="preserve">// User side chunk object. |
|
33 RChunk chunkTx; |
|
34 |
|
35 // Get the handle to the chunk. A driver creates the chunk and |
|
36 // returns the handle to the user to access it. The handle is |
|
37 // assigned to the user side chunk object using RChunk::SetHandle(). |
|
38 // (here done in the GetTxChunkHandle function). The handle has to be a positive |
|
39 // value. It can be obtained using RChunk::Handle(), if required. |
|
40 // |
|
41 r=ldd.GetTxChunkHandle(chunkTx); |
|
42 test(r==KErrNone); |
|
43 |
|
44 // Create a constant descriptor with test data |
|
45 _LIT8(KTestSendData,"<< TEST DATA FOR TUTORIAL DRIVER EXAMPLE >>"); |
|
46 |
|
47 TUint8* chunkbase; |
|
48 // Retrieve the base address of the chunk. Using this address, the user |
|
49 // can access the shared chunk just like any memory pointer. |
|
50 // RChunk::Base() returns the linear address of the shared chunk. |
|
51 // |
|
52 chunkbase=chunkTx.Base(); |
|
53 |
|
54 // Write the data to the shared chunk, using the chunk base address. |
|
55 // Note here we do not need to send data to the driver. We just write to |
|
56 // the buffer and the driver directly accesses the chunk from the kernel side. |
|
57 // |
|
58 TPtr8 inbuf(chunkbase,KTestSendData().Size()); |
|
59 inbuf = KTestSendData; |
|
60 … |
|
61 |
|
62 // Call the LDD interface TransmitData(). There is no need to send the |
|
63 // data, instead we send only a TRequestStatus object (as it's an |
|
64 // asynchronous function), and buffer size. If required, an offset in the shared chunk |
|
65 // can be passed to the driver. |
|
66 r = ldd.TransmitData(txStatus,inbuf.Size()); |
|
67 test(r==KErrNone);</codeblock> </section> |
|
68 <section id="GUID-5524489D-37FB-41CF-BC87-540569FF943F"><title>Kernel-side access</title> <p>On the kernel side, a chunk |
|
69 is represented by a <xref href="GUID-85454082-6734-3F1D-983F-734D4C2AB12D.dita"><apiname>DChunk</apiname></xref> object. A chunk is created, |
|
70 mapped, or opened as shown in earlier sections. The linear and physical addresses |
|
71 of the chunk are returned when this is done. At a later stage in the driver, |
|
72 use <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-626CCD99-63D8-322A-A807-9DB96523C82D"><apiname>Kern::ChunkAddress()</apiname></xref> and <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-79F110C1-2764-34B5-857B-6C0012D2049D"><apiname>Kern::ChunkPhysicalAddress()</apiname></xref> to |
|
73 get the linear and physical addresses respectively. A chunk is read or written |
|
74 to using this address pointer and an offset. </p> <codeblock id="GUID-1E341298-F67A-5A21-8C21-405E1BB97946" xml:space="preserve">// Note: Following lines of code are located in different |
|
75 // functions and different files. Here they are shown together for |
|
76 // easy comprehension. |
|
77 |
|
78 // Linear address of the Rx Shared chunk |
|
79 TLinAddr iRxChunkKernAddr; |
|
80 ... |
|
81 |
|
82 // iRxChunkKernAddr returns the linear address of the Rx chunk |
|
83 TInt r=Kern::ChunkCreate(info,chunk,iRxChunkKernAddr, mapAttr); |
|
84 ... |
|
85 |
|
86 // iRxBufPhysAddr returns the physical address of the Rx chunk |
|
87 r=Kern::ChunkCommitContiguous(chunk, bufoffset, size, iRxBufPhysAddr); |
|
88 ... |
|
89 |
|
90 // Here we are directly using the linear address of the shared |
|
91 // chunk, and so can get rid of any buffer copies. If the DMA |
|
92 // port supports physical address, then the physical address can be |
|
93 // used instead of a linear address. |
|
94 // |
|
95 TInt retval = iRxDmaRequest->Fragment( |
|
96 TUint32)iUartComm->iPortAddr+KHoUART_RHR, |
|
97 TUint32)(iUartComm->iRxChunkKernAddr), aCount, |
|
98 KDmaMemDest|KDmaIncDest, 0 /* no HW Flags*/);</codeblock> <p>Synchronization |
|
99 between user access and kernel access to a shared chunk is handled by the |
|
100 shared chunk API. </p></section> |
|
101 </conbody></concept> |