]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyBlock.c
Update the copyright notice format
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaFloppyDxe / IsaFloppyBlock.c
1 /** @file
2 Implementation of the EFI Block IO Protocol for ISA Floppy driver
3
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
9
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.
12
13 **/
14
15 #include "IsaFloppy.h"
16
17 /**
18 Reset the Block Device.
19
20 @param This Indicates a pointer to the calling context.
21 @param ExtendedVerification Driver may perform diagnostics on reset.
22
23 @retval EFI_SUCCESS The device was reset.
24 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
25 not be reset.
26 **/
27 EFI_STATUS
28 EFIAPI
29 FdcReset (
30 IN EFI_BLOCK_IO_PROTOCOL *This,
31 IN BOOLEAN ExtendedVerification
32 )
33 {
34 FDC_BLK_IO_DEV *FdcDev;
35
36 //
37 // Reset the Floppy Disk Controller
38 //
39 FdcDev = FDD_BLK_IO_FROM_THIS (This);
40
41 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
42 EFI_PROGRESS_CODE,
43 EFI_P_PC_RESET | EFI_PERIPHERAL_REMOVABLE_MEDIA,
44 FdcDev->DevicePath
45 );
46
47 return FddReset (FdcDev);
48 }
49
50 /**
51 Flush the Block Device.
52
53 @param This Indicates a pointer to the calling context.
54
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.
58
59 **/
60 EFI_STATUS
61 EFIAPI
62 FddFlushBlocks (
63 IN EFI_BLOCK_IO_PROTOCOL *This
64 )
65 {
66 //
67 // Not supported yet
68 //
69 return EFI_SUCCESS;
70 }
71
72 /**
73 Common report status code interface.
74
75 @param This Pointer of FDC_BLK_IO_DEV instance
76 @param Read Read or write operation when error occurrs
77 **/
78 VOID
79 FddReportStatus (
80 IN EFI_BLOCK_IO_PROTOCOL *This,
81 IN BOOLEAN Read
82 )
83 {
84 FDC_BLK_IO_DEV *FdcDev;
85
86 FdcDev = FDD_BLK_IO_FROM_THIS (This);
87
88 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
89 EFI_ERROR_CODE,
90 ((Read) ? EFI_P_EC_INPUT_ERROR : EFI_P_EC_OUTPUT_ERROR) | EFI_PERIPHERAL_REMOVABLE_MEDIA,
91 FdcDev->DevicePath
92 );
93 }
94
95 /**
96 Read BufferSize bytes from Lba into Buffer.
97
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.
104
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.
112
113 **/
114 EFI_STATUS
115 EFIAPI
116 FddReadBlocks (
117 IN EFI_BLOCK_IO_PROTOCOL *This,
118 IN UINT32 MediaId,
119 IN EFI_LBA Lba,
120 IN UINTN BufferSize,
121 OUT VOID *Buffer
122 )
123 {
124 EFI_STATUS Status;
125
126 Status = FddReadWriteBlocks (This, MediaId, Lba, BufferSize, READ, Buffer);
127
128 if (EFI_ERROR (Status)) {
129 FddReportStatus (This, TRUE);
130 }
131
132 return Status;
133 }
134
135 /**
136 Write BufferSize bytes from Lba into Buffer.
137
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.
144
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.
153
154 **/
155 EFI_STATUS
156 EFIAPI
157 FddWriteBlocks (
158 IN EFI_BLOCK_IO_PROTOCOL *This,
159 IN UINT32 MediaId,
160 IN EFI_LBA Lba,
161 IN UINTN BufferSize,
162 IN VOID *Buffer
163 )
164 {
165 EFI_STATUS Status;
166
167 Status = FddReadWriteBlocks (This, MediaId, Lba, BufferSize, WRITE, Buffer);
168
169 if (EFI_ERROR (Status)) {
170 FddReportStatus (This, FALSE);
171 }
172
173 return Status;
174 }
175
176 /**
177 Read or Write a number of blocks to floppy disk
178
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.
186
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.
195
196 **/
197 EFI_STATUS
198 FddReadWriteBlocks (
199 IN EFI_BLOCK_IO_PROTOCOL *This,
200 IN UINT32 MediaId,
201 IN EFI_LBA Lba,
202 IN UINTN BufferSize,
203 IN BOOLEAN Operation,
204 OUT VOID *Buffer
205 )
206 {
207 EFI_BLOCK_IO_MEDIA *Media;
208 FDC_BLK_IO_DEV *FdcDev;
209 UINTN BlockSize;
210 UINTN NumberOfBlocks;
211 UINTN BlockCount;
212 EFI_STATUS Status;
213 EFI_LBA Lba0;
214 UINT8 *Pointer;
215
216 //
217 // Get the intrinsic block size
218 //
219 Media = This->Media;
220 BlockSize = Media->BlockSize;
221 FdcDev = FDD_BLK_IO_FROM_THIS (This);
222
223 if (Operation == WRITE) {
224 if (Lba == 0) {
225 FdcFreeCache (FdcDev);
226 }
227 }
228 //
229 // Check the Parameter is valid
230 //
231 if (Buffer == NULL) {
232 return EFI_INVALID_PARAMETER;
233 }
234
235 if (BufferSize == 0) {
236 return EFI_SUCCESS;
237 }
238 //
239 // Set the drive motor on
240 //
241 Status = MotorOn (FdcDev);
242 if (EFI_ERROR (Status)) {
243 return EFI_DEVICE_ERROR;
244 }
245 //
246 // Check to see if media can be detected
247 //
248 Status = DetectMedia (FdcDev);
249 if (EFI_ERROR (Status)) {
250 MotorOff (FdcDev);
251 FdcFreeCache (FdcDev);
252 return EFI_DEVICE_ERROR;
253 }
254 //
255 // Check to see if media is present
256 //
257 if (!(Media->MediaPresent)) {
258 MotorOff (FdcDev);
259 FdcFreeCache (FdcDev);
260 return EFI_NO_MEDIA;
261 }
262 //
263 // Check to see if media has been changed
264 //
265 if (MediaId != Media->MediaId) {
266 MotorOff (FdcDev);
267 FdcFreeCache (FdcDev);
268 return EFI_MEDIA_CHANGED;
269 }
270
271 if (Operation == WRITE) {
272 if (Media->ReadOnly) {
273 MotorOff (FdcDev);
274 return EFI_WRITE_PROTECTED;
275 }
276 }
277 //
278 // Check the parameters for this read/write operation
279 //
280 if (BufferSize % BlockSize != 0) {
281 MotorOff (FdcDev);
282 return EFI_BAD_BUFFER_SIZE;
283 }
284
285 if (Lba > Media->LastBlock) {
286 MotorOff (FdcDev);
287 return EFI_INVALID_PARAMETER;
288 }
289
290 if (((BufferSize / BlockSize) + Lba - 1) > Media->LastBlock) {
291 MotorOff (FdcDev);
292 return EFI_INVALID_PARAMETER;
293 }
294
295 if (Operation == READ) {
296 //
297 // See if the data that is being read is already in the cache
298 //
299 if (FdcDev->Cache != NULL) {
300 if (Lba == 0 && BufferSize == BlockSize) {
301 MotorOff (FdcDev);
302 CopyMem ((UINT8 *) Buffer, (UINT8 *) FdcDev->Cache, BlockSize);
303 return EFI_SUCCESS;
304 }
305 }
306 }
307 //
308 // Set up Floppy Disk Controller
309 //
310 Status = Setup (FdcDev);
311 if (EFI_ERROR (Status)) {
312 MotorOff (FdcDev);
313 return EFI_DEVICE_ERROR;
314 }
315
316 NumberOfBlocks = BufferSize / BlockSize;
317 Lba0 = Lba;
318 Pointer = Buffer;
319
320 //
321 // read blocks in the same cylinder.
322 // in a cylinder , there are 18 * 2 = 36 blocks
323 //
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)) {
328 MotorOff (FdcDev);
329 FddReset (FdcDev);
330 return EFI_DEVICE_ERROR;
331 }
332
333 Lba += BlockCount;
334 NumberOfBlocks -= BlockCount;
335 Buffer = (VOID *) ((UINTN) Buffer + BlockCount * BlockSize);
336 BlockCount = GetTransferBlockCount (FdcDev, Lba, NumberOfBlocks);
337 }
338
339 Buffer = Pointer;
340
341 //
342 // Turn the motor off
343 //
344 MotorOff (FdcDev);
345
346 if (Operation == READ) {
347 //
348 // Cache the data read
349 //
350 if (Lba0 == 0 && FdcDev->Cache == NULL) {
351 FdcDev->Cache = AllocateCopyPool (BlockSize, Buffer);
352 }
353 }
354
355 return EFI_SUCCESS;
356
357 }
358
359 /**
360 Free cache for a floppy disk.
361
362 @param FdcDev A Pointer to FDC_BLK_IO_DEV instance
363
364 **/
365 VOID
366 FdcFreeCache (
367 IN FDC_BLK_IO_DEV *FdcDev
368 )
369 {
370 if (FdcDev->Cache != NULL) {
371 FreePool (FdcDev->Cache);
372 FdcDev->Cache = NULL;
373 }
374 }