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