]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATABlockIo.c
QuarkSocPkg: Add new package for Quark SoC X1000
[mirror_edk2.git] / QuarkSocPkg / QuarkSouthCluster / Sdio / Dxe / SDMediaDeviceDxe / CEATABlockIo.c
CommitLineData
9b6bbcdb
MK
1/** @file\r
2\r
3Block I/O protocol for CE-ATA device\r
4\r
5Copyright (c) 2013-2015 Intel Corporation.\r
6\r
7This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "SDMediaDevice.h"\r
18\r
19/**\r
20 Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.\r
21\r
22 @param This The EFI_BLOCK_IO_PROTOCOL instance.\r
23 @param ExtendedVerification Indicates that the driver may perform a more exhaustive.\r
24 verification operation of the device during reset.\r
25 (This parameter is ingored in this driver.)\r
26\r
27 @retval EFI_SUCCESS Success\r
28**/\r
29EFI_STATUS\r
30EFIAPI\r
31CEATABlockReset (\r
32 IN EFI_BLOCK_IO_PROTOCOL *This,\r
33 IN BOOLEAN ExtendedVerification\r
34 )\r
35{\r
36 EFI_STATUS Status;\r
37 CARD_DATA *CardData;\r
38 EFI_SD_HOST_IO_PROTOCOL *SDHostIo;\r
39\r
40 CardData = CARD_DATA_FROM_THIS(This);\r
41 SDHostIo = CardData->SDHostIo;\r
42\r
43 if (!ExtendedVerification) {\r
44 Status = SoftwareReset (CardData);\r
45 } else {\r
46 Status = SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD);\r
47 if (EFI_ERROR (Status)) {\r
48 DEBUG((EFI_D_ERROR, "CEATABlockReset: Fail to ResetSDHost\n" ));\r
49 return Status;\r
50 }\r
51 Status = MMCSDCardInit (CardData);\r
52 }\r
53\r
54\r
55 return Status;\r
56\r
57 }\r
58\r
59/**\r
60 Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.\r
61\r
62 @param This The EFI_BLOCK_IO_PROTOCOL instance.\r
63 @param MediaId The media id that the write request is for.\r
64 @param LBA The starting logical block address to read from on the device.\r
65 The caller is responsible for writing to only legitimate locations.\r
66 @param BufferSize The size of the Buffer in bytes. This must be a multiple of the\r
67 intrinsic block size of the device.\r
68 @param Buffer A pointer to the destination buffer for the data. The caller\r
69 is responsible for either having implicit or explicit ownership\r
70 of the buffer.\r
71\r
72 @retval EFI_SUCCESS Success\r
73 @retval EFI_DEVICE_ERROR Hardware Error\r
74 @retval EFI_INVALID_PARAMETER Parameter is error\r
75 @retval EFI_NO_MEDIA No media\r
76 @retval EFI_MEDIA_CHANGED Media Change\r
77 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad\r
78**/\r
79EFI_STATUS\r
80EFIAPI\r
81CEATABlockReadBlocks (\r
82 IN EFI_BLOCK_IO_PROTOCOL *This,\r
83 IN UINT32 MediaId,\r
84 IN EFI_LBA LBA,\r
85 IN UINTN BufferSize,\r
86 OUT VOID *Buffer\r
87 )\r
88{\r
89 EFI_STATUS Status;\r
90 CARD_DATA *CardData;\r
91 UINT32 TransferSize;\r
92 UINT8 *pBuf;\r
93 UINT32 Index;\r
94 UINT64 Address;\r
95 UINT32 Remainder;\r
96 UINT64 CEATALBA;\r
97 UINT32 BoundarySize;\r
98\r
99 Status = EFI_SUCCESS;\r
100 CardData = CARD_DATA_FROM_THIS(This);\r
101 pBuf = Buffer;\r
102 Index = 0;\r
103 Address = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize);\r
104 BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize;\r
105\r
106 if (!Buffer) {\r
107 Status = EFI_INVALID_PARAMETER;\r
108 DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));\r
109 goto Exit;\r
110 }\r
111\r
112 if (MediaId != CardData->BlockIoMedia.MediaId) {\r
113 Status = EFI_MEDIA_CHANGED;\r
114 DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Media changed\n" ));\r
115 goto Exit;\r
116 }\r
117\r
118 if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {\r
119 Status = EFI_BAD_BUFFER_SIZE;\r
120 DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Bad buffer size\n" ));\r
121 goto Exit;\r
122 }\r
123\r
124 if (BufferSize == 0) {\r
125 Status = EFI_SUCCESS;\r
126 goto Exit;\r
127 }\r
128\r
129 if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {\r
130 Status = EFI_INVALID_PARAMETER;\r
131 DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));\r
132 goto Exit;\r
133 }\r
134\r
135\r
136 do {\r
137 if (BufferSize < BoundarySize) {\r
138 TransferSize = (UINT32)BufferSize;\r
139 } else {\r
140 TransferSize = BoundarySize;\r
141 }\r
142\r
143 Address += Index * TransferSize;\r
144 CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);\r
145 ASSERT(Remainder == 0);\r
146\r
147 Status = ReadDMAExt (\r
148 CardData,\r
149 CEATALBA,\r
150 pBuf,\r
151 (UINT16)(TransferSize / DATA_UNIT_SIZE)\r
152 );\r
153 if (EFI_ERROR (Status)) {\r
154 DEBUG((EFI_D_ERROR, "Read Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));\r
155 This->Reset (This, TRUE);\r
156 goto Exit;\r
157 }\r
158 BufferSize -= TransferSize;\r
159 pBuf += TransferSize;\r
160 Index ++;\r
161 } while (BufferSize != 0);\r
162\r
163\r
164Exit:\r
165 return Status;\r
166}\r
167\r
168/**\r
169 Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.\r
170\r
171 @param This The EFI_BLOCK_IO_PROTOCOL instance.\r
172 @param MediaId The media id that the write request is for.\r
173 @param LBA The starting logical block address to read from on the device.\r
174 The caller is responsible for writing to only legitimate locations.\r
175 @param BufferSize The size of the Buffer in bytes. This must be a multiple of the\r
176 intrinsic block size of the device.\r
177 @param Buffer A pointer to the destination buffer for the data. The caller\r
178 is responsible for either having implicit or explicit ownership\r
179 of the buffer.\r
180\r
181 @retval EFI_SUCCESS Success\r
182 @retval EFI_DEVICE_ERROR Hardware Error\r
183 @retval EFI_INVALID_PARAMETER Parameter is error\r
184 @retval EFI_NO_MEDIA No media\r
185 @retval EFI_MEDIA_CHANGED Media Change\r
186 @retval EFI_BAD_BUFFER_SIZE Buffer size is bad\r
187**/\r
188EFI_STATUS\r
189EFIAPI\r
190CEATABlockWriteBlocks (\r
191 IN EFI_BLOCK_IO_PROTOCOL *This,\r
192 IN UINT32 MediaId,\r
193 IN EFI_LBA LBA,\r
194 IN UINTN BufferSize,\r
195 IN VOID *Buffer\r
196 )\r
197{\r
198 EFI_STATUS Status;\r
199 CARD_DATA *CardData;\r
200 UINT32 TransferSize;\r
201 UINT8 *pBuf;\r
202 UINT32 Index;\r
203 UINT64 Address;\r
204 UINT32 Remainder;\r
205 UINT64 CEATALBA;\r
206 UINT32 BoundarySize;\r
207\r
208\r
209 Status = EFI_SUCCESS;\r
210 CardData = CARD_DATA_FROM_THIS(This);\r
211 pBuf = Buffer;\r
212 Index = 0;\r
213 Address = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize);\r
214 BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize;\r
215\r
216\r
217 if (!Buffer) {\r
218 Status = EFI_INVALID_PARAMETER;\r
219 goto Exit;\r
220 }\r
221\r
222 if (MediaId != CardData->BlockIoMedia.MediaId) {\r
223 Status = EFI_MEDIA_CHANGED;\r
224 goto Exit;\r
225 }\r
226\r
227 if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {\r
228 Status = EFI_BAD_BUFFER_SIZE;\r
229 goto Exit;\r
230 }\r
231\r
232 if (BufferSize == 0) {\r
233 Status = EFI_SUCCESS;\r
234 goto Exit;\r
235 }\r
236\r
237 if (CardData->BlockIoMedia.ReadOnly) {\r
238 Status = EFI_WRITE_PROTECTED;\r
239 goto Exit;\r
240 }\r
241\r
242 if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {\r
243 Status = EFI_INVALID_PARAMETER;\r
244 goto Exit;\r
245 }\r
246\r
247 CardData->NeedFlush = TRUE;\r
248\r
249 do {\r
250 if (BufferSize < BoundarySize) {\r
251 TransferSize = (UINT32)BufferSize;\r
252 } else {\r
253 TransferSize = BoundarySize;\r
254 }\r
255\r
256 Address += Index * TransferSize;\r
257 CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);\r
258 ASSERT(Remainder == 0);\r
259\r
260 Status = WriteDMAExt (\r
261 CardData,\r
262 CEATALBA,\r
263 pBuf,\r
264 (UINT16)(TransferSize / DATA_UNIT_SIZE)\r
265 );\r
266 if (EFI_ERROR (Status)) {\r
267 DEBUG((EFI_D_ERROR, "Write Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));\r
268 This->Reset (This, TRUE);\r
269 goto Exit;\r
270 }\r
271 BufferSize -= TransferSize;\r
272 pBuf += TransferSize;\r
273 Index ++;\r
274 } while (BufferSize != 0);\r
275\r
276\r
277Exit:\r
278 return Status;\r
279}\r
280\r
281/**\r
282 Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.\r
283 (In this driver, this function just returns EFI_SUCCESS.)\r
284\r
285 @param This The EFI_BLOCK_IO_PROTOCOL instance.\r
286\r
287 @retval EFI_SUCCESS\r
288 @retval Others\r
289**/\r
290EFI_STATUS\r
291EFIAPI\r
292CEATABlockFlushBlocks (\r
293 IN EFI_BLOCK_IO_PROTOCOL *This\r
294 )\r
295{\r
296\r
297 EFI_STATUS Status;\r
298 CARD_DATA *CardData;\r
299\r
300 CardData = CARD_DATA_FROM_THIS(This);\r
301\r
302 if (CardData->NeedFlush) {\r
303 CardData->NeedFlush = FALSE;\r
304 Status = FlushCache (CardData);\r
305 }\r
306\r
307 return EFI_SUCCESS;\r
308}\r
309\r
310\r
311/**\r
312 CEATA card BlockIo init function.\r
313\r
314 @param CardData Pointer to CARD_DATA.\r
315\r
316 @retval EFI_SUCCESS\r
317 @retval Others\r
318**/\r
319EFI_STATUS\r
320CEATABlockIoInit (\r
321 IN CARD_DATA *CardData\r
322 )\r
323/*++\r
324\r
325 Routine Description:\r
326 CEATA card BlockIo init function\r
327\r
328 Arguments:\r
329 CardData - Pointer to CARD_DATA\r
330\r
331 Returns:\r
332 EFI_SUCCESS - Success\r
333--*/\r
334{\r
335 EFI_STATUS Status;\r
336 UINT64 MaxSize;\r
337 UINT32 Remainder;\r
338 //\r
339 //BlockIO protocol\r
340 //\r
341 CardData->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;\r
342 CardData->BlockIo.Media = &(CardData->BlockIoMedia);\r
343 CardData->BlockIo.Reset = CEATABlockReset;\r
344 CardData->BlockIo.ReadBlocks = CEATABlockReadBlocks ;\r
345 CardData->BlockIo.WriteBlocks = CEATABlockWriteBlocks;\r
346 CardData->BlockIo.FlushBlocks = CEATABlockFlushBlocks;\r
347\r
348 CardData->BlockIoMedia.MediaId = 0;\r
349 CardData->BlockIoMedia.RemovableMedia = FALSE;\r
350 CardData->BlockIoMedia.MediaPresent = TRUE;\r
351 CardData->BlockIoMedia.LogicalPartition = FALSE;\r
352\r
353 if (CardData->CSDRegister.PERM_WRITE_PROTECT | CardData->CSDRegister.TMP_WRITE_PROTECT) {\r
354 CardData->BlockIoMedia.ReadOnly = TRUE;\r
355 } else {\r
356 CardData->BlockIoMedia.ReadOnly = FALSE;\r
357 }\r
358\r
359\r
360 CardData->BlockIoMedia.WriteCaching = FALSE;\r
361 CardData->BlockIoMedia.IoAlign = 1;\r
362\r
363 Status = IndentifyDevice (CardData);\r
364 if (EFI_ERROR (Status)) {\r
365 goto Exit;\r
366 }\r
367\r
368 //\r
369 //Some device does not support this feature\r
370 //\r
371\r
372 if (CardData->IndentifyDeviceData.MaxWritesPerAddress == 0) {\r
373 CardData->BlockIoMedia.ReadOnly = TRUE;\r
374 }\r
375\r
376 CardData->BlockIoMedia.BlockSize = (1 << CardData->IndentifyDeviceData.Sectorsize);\r
377 ASSERT(CardData->BlockIoMedia.BlockSize >= 12);\r
378\r
379\r
380 MaxSize = *(UINT64*)(CardData->IndentifyDeviceData.MaximumLBA);\r
381 MaxSize = MultU64x32 (MaxSize, 512);\r
382\r
383 Remainder = 0;\r
384 CardData->BlockNumber = DivU64x32Remainder (MaxSize, CardData->BlockIoMedia.BlockSize, &Remainder);\r
385 ASSERT(Remainder == 0);\r
386\r
387 CardData->BlockIoMedia.LastBlock = (EFI_LBA)(CardData->BlockNumber - 1);\r
388\r
389\r
390Exit:\r
391 return Status;\r
392\r
393}\r
394\r
395\r
396\r