Import IsaFloppy Dxe and Pei in IntelFrameworkModulePkg.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaFloppy / Dxe / IsaFloppyBlock.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation. All rights reserved. <BR>
4 This software and associated documentation (if any) is furnished
5 under a license and may only be used or copied in accordance
6 with the terms of the license. Except as permitted by such
7 license, no part of this software or documentation may be
8 reproduced, stored in a retrieval system, or transmitted in any
9 form or by any means without the express written consent of
10 Intel Corporation.
11
12 Module Name:
13
14 IsaFloppyBlock.c
15
16 Abstract:
17
18 ISA Floppy Driver
19 1. Support two types diskette drive
20 1.44M drive and 2.88M drive (and now only support 1.44M)
21 2. Support two diskette drives
22 3. Use DMA channel 2 to transfer data
23 4. Do not use interrupt
24 5. Support diskette change line signal and write protect
25
26 Implement the Block IO interface
27
28 Revision History:
29
30 --*/
31
32 #include "IsaFloppy.h"
33
34 EFI_STATUS
35 EFIAPI
36 FdcReset (
37 IN EFI_BLOCK_IO_PROTOCOL *This,
38 IN BOOLEAN ExtendedVerification
39 )
40 /*++
41
42 Routine Description: Reset the Floppy Logic Drive, call the FddReset function
43 Parameters:
44 This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
45 ExtendedVerification BOOLEAN: Indicate that the driver may perform a more
46 exhaustive verification operation of the device during
47 reset, now this par is ignored in this driver
48 Returns:
49 EFI_SUCCESS: The Floppy Logic Drive is reset
50 EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly
51 and can not be reset
52
53 --*/
54 // GC_TODO: function comment is missing 'Arguments:'
55 // GC_TODO: This - add argument and description to function comment
56 // GC_TODO: ExtendedVerification - add argument and description to function comment
57 {
58 FDC_BLK_IO_DEV *FdcDev;
59
60 //
61 // Reset the Floppy Disk Controller
62 //
63 FdcDev = FDD_BLK_IO_FROM_THIS (This);
64
65 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
66 EFI_PROGRESS_CODE,
67 EFI_P_PC_RESET | EFI_PERIPHERAL_REMOVABLE_MEDIA,
68 FdcDev->DevicePath
69 );
70
71 return FddReset (FdcDev);
72 }
73
74 EFI_STATUS
75 EFIAPI
76 FddFlushBlocks (
77 IN EFI_BLOCK_IO_PROTOCOL *This
78 )
79 /*++
80
81 Routine Description:
82 Parameters:
83 This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
84 Returns:
85 EFI_SUCCESS:
86
87 --*/
88 // GC_TODO: function comment is missing 'Arguments:'
89 // GC_TODO: This - add argument and description to function comment
90 {
91 //
92 // Not supported yet
93 //
94 return EFI_SUCCESS;
95 }
96
97 STATIC
98 VOID
99 FddReportStatus (
100 IN EFI_BLOCK_IO_PROTOCOL *This,
101 IN BOOLEAN Read
102 )
103 /*++
104
105 Routine Description:
106
107 GC_TODO: Add function description
108
109 Arguments:
110
111 This - GC_TODO: add argument description
112 Read - GC_TODO: add argument description
113
114 Returns:
115
116 GC_TODO: add return values
117
118 --*/
119 {
120 FDC_BLK_IO_DEV *FdcDev;
121
122 FdcDev = FDD_BLK_IO_FROM_THIS (This);
123
124 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
125 EFI_ERROR_CODE,
126 ((Read) ? EFI_P_EC_INPUT_ERROR : EFI_P_EC_OUTPUT_ERROR) | EFI_PERIPHERAL_REMOVABLE_MEDIA,
127 FdcDev->DevicePath
128 );
129 }
130
131 EFI_STATUS
132 EFIAPI
133 FddReadBlocks (
134 IN EFI_BLOCK_IO_PROTOCOL *This,
135 IN UINT32 MediaId,
136 IN EFI_LBA LBA,
137 IN UINTN BufferSize,
138 OUT VOID *Buffer
139 )
140 /*++
141
142 Routine Description: Read the requested number of blocks from the device
143 Parameters:
144 This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
145 MediaId UINT32: The media id that the read request is for
146 LBA EFI_LBA: The starting logic block address to read from on the device
147 BufferSize UINTN: The size of the Buffer in bytes
148 Buffer VOID *: A pointer to the destination buffer for the data
149 Returns:
150 EFI_SUCCESS: The data was read correctly from the device
151 EFI_DEVICE_ERROR:The device reported an error while attempting to perform
152 the read operation
153 EFI_NO_MEDIA: There is no media in the device
154 EFI_MEDIA_CHANGED: The MediaId is not for the current media
155 EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the
156 intrinsic block size of the device
157 EFI_INVALID_PARAMETER:The read request contains LBAs that are not valid,
158 or the buffer is not on proper alignment
159
160 --*/
161 // GC_TODO: function comment is missing 'Arguments:'
162 // GC_TODO: This - add argument and description to function comment
163 // GC_TODO: MediaId - add argument and description to function comment
164 // GC_TODO: LBA - add argument and description to function comment
165 // GC_TODO: BufferSize - add argument and description to function comment
166 // GC_TODO: Buffer - add argument and description to function comment
167 {
168 EFI_STATUS Status;
169
170 Status = FddReadWriteBlocks (This, MediaId, LBA, BufferSize, READ, Buffer);
171
172 if (EFI_ERROR (Status)) {
173 FddReportStatus (This, TRUE);
174 }
175
176 return Status;
177 }
178
179 EFI_STATUS
180 EFIAPI
181 FddWriteBlocks (
182 IN EFI_BLOCK_IO_PROTOCOL *This,
183 IN UINT32 MediaId,
184 IN EFI_LBA LBA,
185 IN UINTN BufferSize,
186 IN VOID *Buffer
187 )
188 /*++
189
190 Routine Description: Write a specified number of blocks to the device
191 Parameters:
192 This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
193 MediaId UINT32: The media id that the write request is for
194 LBA EFI_LBA: The starting logic block address to be written
195 BufferSize UINTN: The size in bytes in Buffer
196 Buffer VOID *: A pointer to the source buffer for the data
197 Returns :
198 EFI_SUCCESS: The data were written correctly to the device
199 EFI_WRITE_PROTECTED: The device can not be written to
200 EFI_NO_MEDIA: There is no media in the device
201 EFI_MEDIA_CHANGED: The MediaId is not for the current media
202 EFI_DEVICE_ERROR: The device reported an error while attempting to perform
203 the write operation
204 EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the
205 intrinsic block size of the device
206 EFI_INVALID_PARAMETER:The write request contains LBAs that are not valid,
207 or the buffer is not on proper alignment
208
209 --*/
210 // GC_TODO: function comment is missing 'Arguments:'
211 // GC_TODO: function comment is missing 'Returns:'
212 // GC_TODO: This - add argument and description to function comment
213 // GC_TODO: MediaId - add argument and description to function comment
214 // GC_TODO: LBA - add argument and description to function comment
215 // GC_TODO: BufferSize - add argument and description to function comment
216 // GC_TODO: Buffer - add argument and description to function comment
217 {
218 EFI_STATUS Status;
219
220 Status = FddReadWriteBlocks (This, MediaId, LBA, BufferSize, WRITE, Buffer);
221
222 if (EFI_ERROR (Status)) {
223 FddReportStatus (This, FALSE);
224 }
225
226 return Status;
227 }
228
229 EFI_STATUS
230 FddReadWriteBlocks (
231 IN EFI_BLOCK_IO_PROTOCOL *This,
232 IN UINT32 MediaId,
233 IN EFI_LBA LBA,
234 IN UINTN BufferSize,
235 IN BOOLEAN Operation,
236 OUT VOID *Buffer
237 )
238 /*++
239
240 Routine Description:
241
242 GC_TODO: Add function description
243
244 Arguments:
245
246 This - GC_TODO: add argument description
247 MediaId - GC_TODO: add argument description
248 LBA - GC_TODO: add argument description
249 BufferSize - GC_TODO: add argument description
250 Operation - GC_TODO: add argument description
251 Buffer - GC_TODO: add argument description
252
253 Returns:
254
255 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
256 EFI_SUCCESS - GC_TODO: Add description for return value
257 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
258 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
259 EFI_NO_MEDIA - GC_TODO: Add description for return value
260 EFI_MEDIA_CHANGED - GC_TODO: Add description for return value
261 EFI_WRITE_PROTECTED - GC_TODO: Add description for return value
262 EFI_BAD_BUFFER_SIZE - GC_TODO: Add description for return value
263 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
264 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
265 EFI_SUCCESS - GC_TODO: Add description for return value
266 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
267 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
268 EFI_SUCCESS - GC_TODO: Add description for return value
269
270 --*/
271 {
272 EFI_BLOCK_IO_MEDIA *Media;
273 FDC_BLK_IO_DEV *FdcDev;
274 UINTN BlockSize;
275 UINTN NumberOfBlocks;
276 UINTN BlockCount;
277 EFI_STATUS Status;
278 //
279 // EFI_STATUS CacheStatus;
280 //
281 EFI_LBA LBA0;
282 UINT8 *Pointer;
283
284 //
285 // Get the intrinsic block size
286 //
287 Media = This->Media;
288 BlockSize = Media->BlockSize;
289 FdcDev = FDD_BLK_IO_FROM_THIS (This);
290
291 if (Operation == WRITE) {
292 if (LBA == 0) {
293 FdcFreeCache (FdcDev);
294 }
295 }
296 //
297 // Check the Parameter is valid
298 //
299 if (Buffer == NULL) {
300 return EFI_INVALID_PARAMETER;
301 }
302
303 if (BufferSize == 0) {
304 return EFI_SUCCESS;
305 }
306 //
307 // Set the drive motor on
308 //
309 Status = MotorOn (FdcDev);
310 if (EFI_ERROR (Status)) {
311 return EFI_DEVICE_ERROR;
312 }
313 //
314 // Check to see if media can be detected
315 //
316 Status = DetectMedia (FdcDev);
317 if (EFI_ERROR (Status)) {
318 MotorOff (FdcDev);
319 FdcFreeCache (FdcDev);
320 return EFI_DEVICE_ERROR;
321 }
322 //
323 // Check to see if media is present
324 //
325 if (!(Media->MediaPresent)) {
326 MotorOff (FdcDev);
327 FdcFreeCache (FdcDev);
328
329 /*
330 if (FdcDev->Cache) {
331 gBS->FreePool (FdcDev->Cache);
332 FdcDev->Cache = NULL;
333 }
334 */
335 return EFI_NO_MEDIA;
336 }
337 //
338 // Check to see if media has been changed
339 //
340 if (MediaId != Media->MediaId) {
341 MotorOff (FdcDev);
342 FdcFreeCache (FdcDev);
343 return EFI_MEDIA_CHANGED;
344 }
345
346 if (Operation == WRITE) {
347 if (Media->ReadOnly) {
348 MotorOff (FdcDev);
349 return EFI_WRITE_PROTECTED;
350 }
351 }
352 //
353 // Check the parameters for this read/write operation
354 //
355 if (BufferSize % BlockSize != 0) {
356 MotorOff (FdcDev);
357 return EFI_BAD_BUFFER_SIZE;
358 }
359
360 if (LBA > Media->LastBlock) {
361 MotorOff (FdcDev);
362 return EFI_INVALID_PARAMETER;
363 }
364
365 if (((BufferSize / BlockSize) + LBA - 1) > Media->LastBlock) {
366 MotorOff (FdcDev);
367 return EFI_INVALID_PARAMETER;
368 }
369
370 if (Operation == READ) {
371 //
372 // See if the data that is being read is already in the cache
373 //
374 if (FdcDev->Cache) {
375 if (LBA == 0 && BufferSize == BlockSize) {
376 MotorOff (FdcDev);
377 CopyMem ((UINT8 *) Buffer, (UINT8 *) FdcDev->Cache, BlockSize);
378 return EFI_SUCCESS;
379 }
380 }
381 }
382 //
383 // Set up Floppy Disk Controller
384 //
385 Status = Setup (FdcDev);
386 if (EFI_ERROR (Status)) {
387 MotorOff (FdcDev);
388 return EFI_DEVICE_ERROR;
389 }
390
391 NumberOfBlocks = BufferSize / BlockSize;
392 LBA0 = LBA;
393 Pointer = Buffer;
394
395 //
396 // read blocks in the same cylinder.
397 // in a cylinder , there are 18 * 2 = 36 blocks
398 //
399 BlockCount = GetTransferBlockCount (FdcDev, LBA, NumberOfBlocks);
400 while ((BlockCount != 0) && !EFI_ERROR (Status)) {
401 Status = ReadWriteDataSector (FdcDev, Buffer, LBA, BlockCount, Operation);
402 if (EFI_ERROR (Status)) {
403 MotorOff (FdcDev);
404 FddReset (FdcDev);
405 return EFI_DEVICE_ERROR;
406 }
407
408 LBA += BlockCount;
409 NumberOfBlocks -= BlockCount;
410 Buffer = (VOID *) ((UINTN) Buffer + BlockCount * BlockSize);
411 BlockCount = GetTransferBlockCount (FdcDev, LBA, NumberOfBlocks);
412 }
413
414 Buffer = Pointer;
415
416 //
417 // Turn the motor off
418 //
419 MotorOff (FdcDev);
420
421 if (Operation == READ) {
422 //
423 // Cache the data read
424 //
425 if (LBA0 == 0 && !FdcDev->Cache) {
426 FdcDev->Cache = AllocateCopyPool (BlockSize, Buffer);
427 }
428 }
429
430 return EFI_SUCCESS;
431
432 }
433
434 VOID
435 FdcFreeCache (
436 IN FDC_BLK_IO_DEV *FdcDev
437 )
438 /*++
439
440 Routine Description:
441
442 GC_TODO: Add function description
443
444 Arguments:
445
446 FdcDev - GC_TODO: add argument description
447
448 Returns:
449
450 GC_TODO: add return values
451
452 --*/
453 {
454 if (FdcDev->Cache) {
455 gBS->FreePool (FdcDev->Cache);
456 FdcDev->Cache = NULL;
457 }
458 }