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