|
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @internalTechnology |
|
19 */ |
|
20 |
|
21 #include <e32def.h> |
|
22 #include <e32std.h> |
|
23 #include <e32base.h> |
|
24 #include "msctypes.h" |
|
25 |
|
26 #include "mblocktransferprotocol.h" |
|
27 #include "tblocktransfer.h" |
|
28 #include "debug.h" |
|
29 #include "msdebug.h" |
|
30 |
|
31 |
|
32 /** |
|
33 Manage a read from a block device. |
|
34 |
|
35 @param aProtocol A reference to object providing protocol read method |
|
36 @param aPosition The position to start reading from |
|
37 @param aLength The length of data to read |
|
38 @param aBuf Buffer to copy the data to |
|
39 */ |
|
40 void TBlockTransfer::ReadL(MBlockTransferProtocol& aProtocol, |
|
41 TPos aPosition, |
|
42 TInt aLength, |
|
43 TDes8& aBuf) |
|
44 { |
|
45 __MSFNLOG |
|
46 __HOSTPRINT1(_L("blocklen = 0%lx"), iBlockLength); |
|
47 |
|
48 TInt copylen = 0; |
|
49 TInt headlen = 0; |
|
50 |
|
51 aBuf.SetLength(0); |
|
52 TPos headOffset = GetHeadBlockOffset(aPosition); |
|
53 /**** READ10 HEAD ****/ |
|
54 if (headOffset) |
|
55 { |
|
56 TPos headpos = aPosition - headOffset; |
|
57 iHeadbuf->Zero(); |
|
58 headlen = ((headOffset + aLength - 1) / iBlockLength) == 0 ? aLength : (iBlockLength - headOffset); |
|
59 |
|
60 __HOSTPRINT2(_L("\tRead head pos = 0%lx length = 0%lx"), |
|
61 headpos, iBlockLength); |
|
62 aProtocol.BlockReadL(headpos, *iHeadbuf, iBlockLength); |
|
63 aBuf.Append(iHeadbuf->Ptr() + headOffset, headlen); |
|
64 } |
|
65 |
|
66 /**** READ10 BODY ****/ |
|
67 TInt blocksInMain = (aLength - headlen)/iBlockLength; |
|
68 if (blocksInMain) |
|
69 { |
|
70 copylen = blocksInMain * iBlockLength; |
|
71 __HOSTPRINT2(_L("\tRead main pos = 0%lx length = 0x%x"), |
|
72 aPosition+headlen, copylen); |
|
73 aProtocol.BlockReadL(aPosition+headlen, (TDes8 &)aBuf, copylen); |
|
74 } |
|
75 |
|
76 copylen += headlen; |
|
77 |
|
78 /**** READ10 TAIL ****/ |
|
79 TInt tailLen = aLength - copylen; |
|
80 if ((tailLen) != 0) |
|
81 { |
|
82 __HOSTPRINT2(_L("\tRead tail pos = 0%lx length = 0%lx"), |
|
83 aPosition+copylen, iBlockLength); |
|
84 iTailbuf->Zero(); |
|
85 aProtocol.BlockReadL(aPosition+copylen, *iTailbuf, iBlockLength); |
|
86 aBuf.Append(iTailbuf->Ptr(), tailLen); |
|
87 } |
|
88 } |
|
89 |
|
90 |
|
91 /** |
|
92 Manage a write to a block device |
|
93 |
|
94 @param aProtocol A reference to object providing protocol read method |
|
95 @param aPosition The position to start reading from |
|
96 @param aLength The length of data to read |
|
97 @param aBuf Buffer containing the data to write |
|
98 */ |
|
99 void TBlockTransfer::WriteL(MBlockTransferProtocol& aProtocol, |
|
100 TPos aPosition, |
|
101 TInt aLength, |
|
102 TDesC8& aBuf) |
|
103 { |
|
104 __MSFNLOG |
|
105 TInt copylen = 0; |
|
106 TInt headlen = 0; |
|
107 |
|
108 TPos headOffset = GetHeadBlockOffset(aPosition); |
|
109 /**** WRITE10 HEAD ****/ |
|
110 if (headOffset) |
|
111 { |
|
112 TPos headpos = aPosition - headOffset; |
|
113 |
|
114 iHeadbuf->Zero(); |
|
115 |
|
116 RBuf8& buf = *iTailbuf; |
|
117 buf.Zero(); |
|
118 |
|
119 headlen = ((headOffset + aLength - 1) / iBlockLength) == 0 ? aLength : (iBlockLength - headOffset); |
|
120 |
|
121 __HOSTPRINT2(_L("\tWrite-Read head pos = 0%lx length = 0%lx"), |
|
122 headpos, iBlockLength); |
|
123 |
|
124 aProtocol.BlockReadL(headpos, *iHeadbuf, iBlockLength); |
|
125 /* get head */ |
|
126 __HOSTPRINT2(_L("\tcopying read data pos = 0%lx offset = 0%lx"), |
|
127 headpos, headOffset); |
|
128 buf.Append(iHeadbuf->Ptr(), headOffset); |
|
129 |
|
130 /* get body */ |
|
131 buf.Append(aBuf.Ptr(), headlen); |
|
132 |
|
133 /* Is it a short write and tail exist? */ |
|
134 TInt headEndOffset = headOffset + headlen; |
|
135 if (headEndOffset != iBlockLength) |
|
136 { |
|
137 TInt len = iBlockLength - headEndOffset; |
|
138 |
|
139 __HOSTPRINT2(_L("\t(short write) copying read data pos = 0%lx length = %08x"), |
|
140 (headpos + headEndOffset), len); |
|
141 buf.Append(iHeadbuf->Ptr() + headEndOffset, len); |
|
142 } |
|
143 |
|
144 __HOSTPRINT2(_L("\tWrite head pos = 0%lx length = %08x"), |
|
145 headpos, headlen); |
|
146 |
|
147 aProtocol.BlockWriteL(headpos, (TDes8 &)buf, 0, iBlockLength); |
|
148 } |
|
149 |
|
150 /**** WRITE10 BODY ****/ |
|
151 TPos blocksInMain = (aLength - headlen)/iBlockLength; |
|
152 if (blocksInMain) |
|
153 { |
|
154 copylen = blocksInMain * iBlockLength; |
|
155 |
|
156 const TUint64 pos = aPosition + headlen; |
|
157 __HOSTPRINT2(_L("\tWrite main pos = 0%lx length = %08x"), |
|
158 pos, copylen); |
|
159 |
|
160 /* form the body */ |
|
161 aProtocol.BlockWriteL(pos, (TDes8 &)aBuf, headlen, copylen); |
|
162 } |
|
163 |
|
164 copylen += headlen; |
|
165 |
|
166 /**** WRITE10 TAIL ****/ |
|
167 TInt tailLen = aLength - copylen;; |
|
168 if (tailLen != 0) |
|
169 { |
|
170 RBuf8& buf = *iHeadbuf; |
|
171 buf.Zero(); |
|
172 |
|
173 iTailbuf->Zero(); |
|
174 |
|
175 const TUint64 pos = aPosition + copylen; |
|
176 |
|
177 __HOSTPRINT2(_L("\tWrite-Read tail pos = 0%lx length = %08x"), |
|
178 pos, iBlockLength); |
|
179 |
|
180 aProtocol.BlockReadL(pos, *iTailbuf, iBlockLength); |
|
181 /* get head */ |
|
182 buf.Append(aBuf.Ptr() + copylen, tailLen); |
|
183 /* get tail */ |
|
184 buf.Append(iTailbuf->Ptr() + tailLen, iBlockLength - tailLen); |
|
185 |
|
186 aProtocol.BlockWriteL(pos, (TDes8 &)buf, 0, iBlockLength); |
|
187 } |
|
188 } |
|
189 |
|
190 |
|
191 void TBlockTransfer::SetCapacityL(TUint32 aBlockLength, TLba aLastLba) |
|
192 { |
|
193 __MSFNLOG |
|
194 iBlockLength = static_cast<TInt64>(aBlockLength); |
|
195 iLastLba = aLastLba; |
|
196 |
|
197 __ASSERT_DEBUG(iHeadbuf, User::Invariant()); |
|
198 __ASSERT_DEBUG(iTailbuf, User::Invariant()); |
|
199 |
|
200 if (iHeadbuf->Length() < iBlockLength) |
|
201 { |
|
202 iHeadbuf->ReAllocL(aBlockLength); |
|
203 iTailbuf->ReAllocL(aBlockLength); |
|
204 } |
|
205 } |
|
206 |
|
207 |
|
208 TPos TBlockTransfer::GetHeadBlockOffset(TPos aPos) |
|
209 { |
|
210 __MSFNLOG |
|
211 return (aPos % iBlockLength); |
|
212 } |
|
213 |
|
214 TLba TBlockTransfer::GetHeadBlockLbaL(TPos aPos) |
|
215 { |
|
216 __MSFNLOG |
|
217 TLba lba = I64LOW(aPos / iBlockLength); |
|
218 if (lba > iLastLba) |
|
219 User::Leave(KErrArgument); |
|
220 return lba; |
|
221 } |
|
222 |
|
223 TPos TBlockTransfer::GetTailBlockOffset(TPos aPos, TInt aLen) |
|
224 { |
|
225 __MSFNLOG |
|
226 return ((aPos + aLen) % iBlockLength); |
|
227 } |
|
228 |
|
229 TLba TBlockTransfer::GetTailBlockLbaL(TPos aPos, TInt aLen) |
|
230 { |
|
231 __MSFNLOG |
|
232 TLba lba = I64LOW((aPos + aLen) / iBlockLength); |
|
233 if (lba > iLastLba) |
|
234 User::Leave(KErrArgument); |
|
235 return lba; |
|
236 } |
|
237 |
|
238 |
|
239 |