]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyBlock.c
Change BlockIo drivers to return EFI_NO_MEDIA or EFI_MEDIA_CHANGED even the Buffer...
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaFloppyDxe / IsaFloppyBlock.c
CommitLineData
d6321d6e 1/** @file \r
2 Implementation of the EFI Block IO Protocol for ISA Floppy driver\r
11f43dfd 3 \r
180a5a35
HT
4Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
f8cd287b 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11f43dfd 12\r
f8cd287b 13**/\r
11f43dfd 14\r
11f43dfd 15#include "IsaFloppy.h"\r
16\r
bcd70414 17/**\r
d6321d6e 18 Reset the Block Device.\r
19\r
20 @param This Indicates a pointer to the calling context.\r
21 @param ExtendedVerification Driver may perform diagnostics on reset.\r
bcd70414 22\r
d6321d6e 23 @retval EFI_SUCCESS The device was reset.\r
24 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
25 not be reset.\r
bcd70414 26**/\r
11f43dfd 27EFI_STATUS\r
28EFIAPI\r
29FdcReset (\r
30 IN EFI_BLOCK_IO_PROTOCOL *This,\r
31 IN BOOLEAN ExtendedVerification\r
32 )\r
11f43dfd 33{\r
34 FDC_BLK_IO_DEV *FdcDev;\r
35\r
36 //\r
37 // Reset the Floppy Disk Controller\r
38 //\r
39 FdcDev = FDD_BLK_IO_FROM_THIS (This);\r
40\r
41 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
42 EFI_PROGRESS_CODE,\r
43 EFI_P_PC_RESET | EFI_PERIPHERAL_REMOVABLE_MEDIA,\r
44 FdcDev->DevicePath\r
45 );\r
46\r
47 return FddReset (FdcDev);\r
48}\r
49\r
bcd70414 50/**\r
d6321d6e 51 Flush the Block Device.\r
52\r
53 @param This Indicates a pointer to the calling context.\r
54\r
55 @retval EFI_SUCCESS All outstanding data was written to the device\r
56 @retval EFI_DEVICE_ERROR The device reported an error while writting back the data\r
57 @retval EFI_NO_MEDIA There is no media in the device.\r
bcd70414 58\r
59**/\r
11f43dfd 60EFI_STATUS\r
61EFIAPI\r
62FddFlushBlocks (\r
63 IN EFI_BLOCK_IO_PROTOCOL *This\r
64 )\r
11f43dfd 65{\r
66 //\r
67 // Not supported yet\r
68 //\r
69 return EFI_SUCCESS;\r
70}\r
71\r
bcd70414 72/**\r
d6321d6e 73 Common report status code interface.\r
bcd70414 74 \r
75 @param This Pointer of FDC_BLK_IO_DEV instance\r
d6321d6e 76 @param Read Read or write operation when error occurrs\r
bcd70414 77**/\r
11f43dfd 78VOID\r
79FddReportStatus (\r
80 IN EFI_BLOCK_IO_PROTOCOL *This,\r
81 IN BOOLEAN Read\r
82 )\r
11f43dfd 83{\r
84 FDC_BLK_IO_DEV *FdcDev;\r
85\r
86 FdcDev = FDD_BLK_IO_FROM_THIS (This);\r
87\r
88 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
89 EFI_ERROR_CODE,\r
90 ((Read) ? EFI_P_EC_INPUT_ERROR : EFI_P_EC_OUTPUT_ERROR) | EFI_PERIPHERAL_REMOVABLE_MEDIA,\r
91 FdcDev->DevicePath\r
92 );\r
93}\r
94\r
bcd70414 95/**\r
d6321d6e 96 Read BufferSize bytes from Lba into Buffer.\r
97\r
98 @param This Indicates a pointer to the calling context.\r
99 @param MediaId Id of the media, changes every time the media is replaced.\r
100 @param Lba The starting Logical Block Address to read from\r
101 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
102 @param Buffer A pointer to the destination buffer for the data. The caller is\r
103 responsible for either having implicit or explicit ownership of the buffer.\r
104\r
105 @retval EFI_SUCCESS The data was read correctly from the device.\r
106 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
107 @retval EFI_NO_MEDIA There is no media in the device.\r
108 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
109 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
110 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
111 or the buffer is not on proper alignment.\r
bcd70414 112\r
113**/\r
11f43dfd 114EFI_STATUS\r
115EFIAPI\r
116FddReadBlocks (\r
117 IN EFI_BLOCK_IO_PROTOCOL *This,\r
118 IN UINT32 MediaId,\r
d6321d6e 119 IN EFI_LBA Lba,\r
11f43dfd 120 IN UINTN BufferSize,\r
121 OUT VOID *Buffer\r
122 )\r
11f43dfd 123{\r
124 EFI_STATUS Status;\r
125\r
d6321d6e 126 Status = FddReadWriteBlocks (This, MediaId, Lba, BufferSize, READ, Buffer);\r
11f43dfd 127\r
128 if (EFI_ERROR (Status)) {\r
129 FddReportStatus (This, TRUE);\r
130 }\r
131\r
132 return Status;\r
133}\r
134\r
bcd70414 135/**\r
d6321d6e 136 Write BufferSize bytes from Lba into Buffer.\r
137\r
138 @param This Indicates a pointer to the calling context.\r
139 @param MediaId The media ID that the write request is for.\r
140 @param Lba The starting logical block address to be written. The caller is\r
141 responsible for writing to only legitimate locations.\r
142 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
143 @param Buffer A pointer to the source buffer for the data.\r
144\r
145 @retval EFI_SUCCESS The data was written correctly to the device.\r
146 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
147 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
148 @retval EFI_NO_MEDIA There is no media in the device.\r
149 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
150 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
151 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
152 or the buffer is not on proper alignment.\r
153\r
bcd70414 154**/\r
11f43dfd 155EFI_STATUS\r
156EFIAPI\r
157FddWriteBlocks (\r
158 IN EFI_BLOCK_IO_PROTOCOL *This,\r
159 IN UINT32 MediaId,\r
d6321d6e 160 IN EFI_LBA Lba,\r
11f43dfd 161 IN UINTN BufferSize,\r
162 IN VOID *Buffer\r
163 )\r
11f43dfd 164{\r
165 EFI_STATUS Status;\r
166\r
d6321d6e 167 Status = FddReadWriteBlocks (This, MediaId, Lba, BufferSize, WRITE, Buffer);\r
11f43dfd 168\r
169 if (EFI_ERROR (Status)) {\r
170 FddReportStatus (This, FALSE);\r
171 }\r
172\r
173 return Status;\r
174}\r
175\r
bcd70414 176/**\r
d6321d6e 177 Read or Write a number of blocks to floppy disk\r
178\r
179 @param This Indicates a pointer to the calling context.\r
180 @param MediaId Id of the media, changes every time the media is replaced.\r
181 @param Lba The starting Logical Block Address to read from\r
182 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
183 @param Operation Specifies the read or write operation.\r
184 @param Buffer A pointer to the destination buffer for the data. The caller is\r
185 responsible for either having implicit or explicit ownership of the buffer.\r
186\r
187 @retval EFI_SUCCESS The data was read correctly from the device.\r
188 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
189 @retval EFI_NO_MEDIA There is no media in the device.\r
190 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
191 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
192 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
193 or the buffer is not on proper alignment.\r
194 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
bcd70414 195\r
196**/\r
11f43dfd 197EFI_STATUS\r
198FddReadWriteBlocks (\r
199 IN EFI_BLOCK_IO_PROTOCOL *This,\r
200 IN UINT32 MediaId,\r
d6321d6e 201 IN EFI_LBA Lba,\r
11f43dfd 202 IN UINTN BufferSize,\r
203 IN BOOLEAN Operation,\r
204 OUT VOID *Buffer\r
205 )\r
11f43dfd 206{\r
207 EFI_BLOCK_IO_MEDIA *Media;\r
208 FDC_BLK_IO_DEV *FdcDev;\r
209 UINTN BlockSize;\r
210 UINTN NumberOfBlocks;\r
211 UINTN BlockCount;\r
212 EFI_STATUS Status;\r
d6321d6e 213 EFI_LBA Lba0;\r
11f43dfd 214 UINT8 *Pointer;\r
215\r
216 //\r
217 // Get the intrinsic block size\r
218 //\r
219 Media = This->Media;\r
220 BlockSize = Media->BlockSize;\r
221 FdcDev = FDD_BLK_IO_FROM_THIS (This);\r
222\r
223 if (Operation == WRITE) {\r
d6321d6e 224 if (Lba == 0) {\r
11f43dfd 225 FdcFreeCache (FdcDev);\r
226 }\r
227 }\r
11f43dfd 228\r
11f43dfd 229 //\r
230 // Set the drive motor on\r
231 //\r
232 Status = MotorOn (FdcDev);\r
233 if (EFI_ERROR (Status)) {\r
234 return EFI_DEVICE_ERROR;\r
235 }\r
236 //\r
237 // Check to see if media can be detected\r
238 //\r
239 Status = DetectMedia (FdcDev);\r
240 if (EFI_ERROR (Status)) {\r
241 MotorOff (FdcDev);\r
242 FdcFreeCache (FdcDev);\r
243 return EFI_DEVICE_ERROR;\r
244 }\r
245 //\r
246 // Check to see if media is present\r
247 //\r
248 if (!(Media->MediaPresent)) {\r
249 MotorOff (FdcDev);\r
250 FdcFreeCache (FdcDev);\r
11f43dfd 251 return EFI_NO_MEDIA;\r
252 }\r
253 //\r
254 // Check to see if media has been changed\r
255 //\r
256 if (MediaId != Media->MediaId) {\r
257 MotorOff (FdcDev);\r
258 FdcFreeCache (FdcDev);\r
259 return EFI_MEDIA_CHANGED;\r
260 }\r
261\r
5d7ca124
RN
262 if (BufferSize == 0) {\r
263 MotorOff (FdcDev);\r
264 return EFI_SUCCESS;\r
265 }\r
266\r
11f43dfd 267 if (Operation == WRITE) {\r
268 if (Media->ReadOnly) {\r
269 MotorOff (FdcDev);\r
270 return EFI_WRITE_PROTECTED;\r
271 }\r
272 }\r
273 //\r
274 // Check the parameters for this read/write operation\r
275 //\r
5d7ca124
RN
276 if (Buffer == NULL) {\r
277 MotorOff (FdcDev);\r
278 return EFI_INVALID_PARAMETER;\r
279 }\r
280\r
11f43dfd 281 if (BufferSize % BlockSize != 0) {\r
282 MotorOff (FdcDev);\r
283 return EFI_BAD_BUFFER_SIZE;\r
284 }\r
285\r
d6321d6e 286 if (Lba > Media->LastBlock) {\r
11f43dfd 287 MotorOff (FdcDev);\r
288 return EFI_INVALID_PARAMETER;\r
289 }\r
290\r
d6321d6e 291 if (((BufferSize / BlockSize) + Lba - 1) > Media->LastBlock) {\r
11f43dfd 292 MotorOff (FdcDev);\r
293 return EFI_INVALID_PARAMETER;\r
294 }\r
295\r
296 if (Operation == READ) {\r
297 //\r
298 // See if the data that is being read is already in the cache\r
299 //\r
d6321d6e 300 if (FdcDev->Cache != NULL) {\r
301 if (Lba == 0 && BufferSize == BlockSize) {\r
11f43dfd 302 MotorOff (FdcDev);\r
303 CopyMem ((UINT8 *) Buffer, (UINT8 *) FdcDev->Cache, BlockSize);\r
304 return EFI_SUCCESS;\r
305 }\r
306 }\r
307 }\r
308 //\r
309 // Set up Floppy Disk Controller\r
310 //\r
311 Status = Setup (FdcDev);\r
312 if (EFI_ERROR (Status)) {\r
313 MotorOff (FdcDev);\r
314 return EFI_DEVICE_ERROR;\r
315 }\r
316\r
317 NumberOfBlocks = BufferSize / BlockSize;\r
d6321d6e 318 Lba0 = Lba;\r
11f43dfd 319 Pointer = Buffer;\r
320\r
321 //\r
322 // read blocks in the same cylinder.\r
323 // in a cylinder , there are 18 * 2 = 36 blocks\r
324 //\r
d6321d6e 325 BlockCount = GetTransferBlockCount (FdcDev, Lba, NumberOfBlocks);\r
11f43dfd 326 while ((BlockCount != 0) && !EFI_ERROR (Status)) {\r
d6321d6e 327 Status = ReadWriteDataSector (FdcDev, Buffer, Lba, BlockCount, Operation);\r
11f43dfd 328 if (EFI_ERROR (Status)) {\r
329 MotorOff (FdcDev);\r
330 FddReset (FdcDev);\r
331 return EFI_DEVICE_ERROR;\r
332 }\r
333\r
d6321d6e 334 Lba += BlockCount;\r
11f43dfd 335 NumberOfBlocks -= BlockCount;\r
336 Buffer = (VOID *) ((UINTN) Buffer + BlockCount * BlockSize);\r
d6321d6e 337 BlockCount = GetTransferBlockCount (FdcDev, Lba, NumberOfBlocks);\r
11f43dfd 338 }\r
339\r
340 Buffer = Pointer;\r
341\r
342 //\r
343 // Turn the motor off\r
344 //\r
345 MotorOff (FdcDev);\r
346\r
347 if (Operation == READ) {\r
348 //\r
349 // Cache the data read\r
350 //\r
d6321d6e 351 if (Lba0 == 0 && FdcDev->Cache == NULL) {\r
11f43dfd 352 FdcDev->Cache = AllocateCopyPool (BlockSize, Buffer);\r
353 }\r
354 }\r
355\r
356 return EFI_SUCCESS;\r
357\r
358}\r
359\r
bcd70414 360/**\r
d6321d6e 361 Free cache for a floppy disk.\r
bcd70414 362 \r
d6321d6e 363 @param FdcDev A Pointer to FDC_BLK_IO_DEV instance\r
bcd70414 364 \r
365**/\r
11f43dfd 366VOID\r
367FdcFreeCache (\r
d6321d6e 368 IN FDC_BLK_IO_DEV *FdcDev\r
11f43dfd 369 )\r
11f43dfd 370{\r
d6321d6e 371 if (FdcDev->Cache != NULL) {\r
372 FreePool (FdcDev->Cache);\r
11f43dfd 373 FdcDev->Cache = NULL;\r
374 }\r
375}\r