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