2 Implementation of the EFI Block IO Protocol for ISA Floppy driver
4 Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "IsaFloppy.h"
18 Reset the Block Device.
20 @param This Indicates a pointer to the calling context.
21 @param ExtendedVerification Driver may perform diagnostics on reset.
23 @retval EFI_SUCCESS The device was reset.
24 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
30 IN EFI_BLOCK_IO_PROTOCOL
*This
,
31 IN BOOLEAN ExtendedVerification
34 FDC_BLK_IO_DEV
*FdcDev
;
37 // Reset the Floppy Disk Controller
39 FdcDev
= FDD_BLK_IO_FROM_THIS (This
);
41 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
43 EFI_P_PC_RESET
| EFI_PERIPHERAL_REMOVABLE_MEDIA
,
47 return FddReset (FdcDev
);
51 Flush the Block Device.
53 @param This Indicates a pointer to the calling context.
55 @retval EFI_SUCCESS All outstanding data was written to the device
56 @retval EFI_DEVICE_ERROR The device reported an error while writting back the data
57 @retval EFI_NO_MEDIA There is no media in the device.
63 IN EFI_BLOCK_IO_PROTOCOL
*This
73 Common report status code interface.
75 @param This Pointer of FDC_BLK_IO_DEV instance
76 @param Read Read or write operation when error occurrs
80 IN EFI_BLOCK_IO_PROTOCOL
*This
,
84 FDC_BLK_IO_DEV
*FdcDev
;
86 FdcDev
= FDD_BLK_IO_FROM_THIS (This
);
88 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
90 ((Read
) ? EFI_P_EC_INPUT_ERROR
: EFI_P_EC_OUTPUT_ERROR
) | EFI_PERIPHERAL_REMOVABLE_MEDIA
,
96 Read BufferSize bytes from Lba into Buffer.
98 @param This Indicates a pointer to the calling context.
99 @param MediaId Id of the media, changes every time the media is replaced.
100 @param Lba The starting Logical Block Address to read from
101 @param BufferSize Size of Buffer, must be a multiple of device block size.
102 @param Buffer A pointer to the destination buffer for the data. The caller is
103 responsible for either having implicit or explicit ownership of the buffer.
105 @retval EFI_SUCCESS The data was read correctly from the device.
106 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
107 @retval EFI_NO_MEDIA There is no media in the device.
108 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
109 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
110 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
111 or the buffer is not on proper alignment.
117 IN EFI_BLOCK_IO_PROTOCOL
*This
,
126 Status
= FddReadWriteBlocks (This
, MediaId
, Lba
, BufferSize
, READ
, Buffer
);
128 if (EFI_ERROR (Status
)) {
129 FddReportStatus (This
, TRUE
);
136 Write BufferSize bytes from Lba into Buffer.
138 @param This Indicates a pointer to the calling context.
139 @param MediaId The media ID that the write request is for.
140 @param Lba The starting logical block address to be written. The caller is
141 responsible for writing to only legitimate locations.
142 @param BufferSize Size of Buffer, must be a multiple of device block size.
143 @param Buffer A pointer to the source buffer for the data.
145 @retval EFI_SUCCESS The data was written correctly to the device.
146 @retval EFI_WRITE_PROTECTED The device can not be written to.
147 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
148 @retval EFI_NO_MEDIA There is no media in the device.
149 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
150 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
151 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
152 or the buffer is not on proper alignment.
158 IN EFI_BLOCK_IO_PROTOCOL
*This
,
167 Status
= FddReadWriteBlocks (This
, MediaId
, Lba
, BufferSize
, WRITE
, Buffer
);
169 if (EFI_ERROR (Status
)) {
170 FddReportStatus (This
, FALSE
);
177 Read or Write a number of blocks to floppy disk
179 @param This Indicates a pointer to the calling context.
180 @param MediaId Id of the media, changes every time the media is replaced.
181 @param Lba The starting Logical Block Address to read from
182 @param BufferSize Size of Buffer, must be a multiple of device block size.
183 @param Operation Specifies the read or write operation.
184 @param Buffer A pointer to the destination buffer for the data. The caller is
185 responsible for either having implicit or explicit ownership of the buffer.
187 @retval EFI_SUCCESS The data was read correctly from the device.
188 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
189 @retval EFI_NO_MEDIA There is no media in the device.
190 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
191 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
192 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
193 or the buffer is not on proper alignment.
194 @retval EFI_WRITE_PROTECTED The device can not be written to.
199 IN EFI_BLOCK_IO_PROTOCOL
*This
,
203 IN BOOLEAN Operation
,
207 EFI_BLOCK_IO_MEDIA
*Media
;
208 FDC_BLK_IO_DEV
*FdcDev
;
210 UINTN NumberOfBlocks
;
217 // Get the intrinsic block size
220 BlockSize
= Media
->BlockSize
;
221 FdcDev
= FDD_BLK_IO_FROM_THIS (This
);
223 if (Operation
== WRITE
) {
225 FdcFreeCache (FdcDev
);
229 // Check the Parameter is valid
231 if (Buffer
== NULL
) {
232 return EFI_INVALID_PARAMETER
;
235 if (BufferSize
== 0) {
239 // Set the drive motor on
241 Status
= MotorOn (FdcDev
);
242 if (EFI_ERROR (Status
)) {
243 return EFI_DEVICE_ERROR
;
246 // Check to see if media can be detected
248 Status
= DetectMedia (FdcDev
);
249 if (EFI_ERROR (Status
)) {
251 FdcFreeCache (FdcDev
);
252 return EFI_DEVICE_ERROR
;
255 // Check to see if media is present
257 if (!(Media
->MediaPresent
)) {
259 FdcFreeCache (FdcDev
);
263 // Check to see if media has been changed
265 if (MediaId
!= Media
->MediaId
) {
267 FdcFreeCache (FdcDev
);
268 return EFI_MEDIA_CHANGED
;
271 if (Operation
== WRITE
) {
272 if (Media
->ReadOnly
) {
274 return EFI_WRITE_PROTECTED
;
278 // Check the parameters for this read/write operation
280 if (BufferSize
% BlockSize
!= 0) {
282 return EFI_BAD_BUFFER_SIZE
;
285 if (Lba
> Media
->LastBlock
) {
287 return EFI_INVALID_PARAMETER
;
290 if (((BufferSize
/ BlockSize
) + Lba
- 1) > Media
->LastBlock
) {
292 return EFI_INVALID_PARAMETER
;
295 if (Operation
== READ
) {
297 // See if the data that is being read is already in the cache
299 if (FdcDev
->Cache
!= NULL
) {
300 if (Lba
== 0 && BufferSize
== BlockSize
) {
302 CopyMem ((UINT8
*) Buffer
, (UINT8
*) FdcDev
->Cache
, BlockSize
);
308 // Set up Floppy Disk Controller
310 Status
= Setup (FdcDev
);
311 if (EFI_ERROR (Status
)) {
313 return EFI_DEVICE_ERROR
;
316 NumberOfBlocks
= BufferSize
/ BlockSize
;
321 // read blocks in the same cylinder.
322 // in a cylinder , there are 18 * 2 = 36 blocks
324 BlockCount
= GetTransferBlockCount (FdcDev
, Lba
, NumberOfBlocks
);
325 while ((BlockCount
!= 0) && !EFI_ERROR (Status
)) {
326 Status
= ReadWriteDataSector (FdcDev
, Buffer
, Lba
, BlockCount
, Operation
);
327 if (EFI_ERROR (Status
)) {
330 return EFI_DEVICE_ERROR
;
334 NumberOfBlocks
-= BlockCount
;
335 Buffer
= (VOID
*) ((UINTN
) Buffer
+ BlockCount
* BlockSize
);
336 BlockCount
= GetTransferBlockCount (FdcDev
, Lba
, NumberOfBlocks
);
342 // Turn the motor off
346 if (Operation
== READ
) {
348 // Cache the data read
350 if (Lba0
== 0 && FdcDev
->Cache
== NULL
) {
351 FdcDev
->Cache
= AllocateCopyPool (BlockSize
, Buffer
);
360 Free cache for a floppy disk.
362 @param FdcDev A Pointer to FDC_BLK_IO_DEV instance
367 IN FDC_BLK_IO_DEV
*FdcDev
370 if (FdcDev
->Cache
!= NULL
) {
371 FreePool (FdcDev
->Cache
);
372 FdcDev
->Cache
= NULL
;