]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.c
1. Add NULL QH to set as QH header;
[mirror_edk2.git] / EdkModulePkg / Bus / Usb / UsbMassStorage / Dxe / UsbMassStorage.c
CommitLineData
878ddf1f 1/*++\r
2\r
4d1fe68e 3Copyright (c) 2006, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
878ddf1f 11\r
12Module Name:\r
13\r
14 UsbMassStorage.c\r
4d1fe68e 15\r
878ddf1f 16Abstract:\r
17\r
18 USB Mass Storage Driver\r
19\r
20Revision History\r
21\r
22--*/\r
23\r
24#include "UsbMassStorage.h"\r
25#include "UsbMassStorageHelper.h"\r
26\r
27extern EFI_COMPONENT_NAME_PROTOCOL gUsbMassStorageComponentName;\r
28\r
29//\r
30// Prototypes\r
31// Driver model protocol interface\r
32//\r
33EFI_STATUS\r
34EFIAPI\r
35USBMassStorageDriverBindingEntryPoint (\r
36 IN EFI_HANDLE ImageHandle,\r
37 IN EFI_SYSTEM_TABLE *SystemTable\r
38 );\r
39\r
40EFI_STATUS\r
41EFIAPI\r
42USBFloppyDriverBindingSupported (\r
43 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
44 IN EFI_HANDLE Controller,\r
45 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
46 );\r
47\r
48EFI_STATUS\r
49EFIAPI\r
50USBFloppyDriverBindingStart (\r
51 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
52 IN EFI_HANDLE Controller,\r
53 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
54 );\r
55\r
56EFI_STATUS\r
57EFIAPI\r
58USBFloppyDriverBindingStop (\r
59 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
60 IN EFI_HANDLE Controller,\r
61 IN UINTN NumberOfChildren,\r
62 IN EFI_HANDLE *ChildHandleBuffer\r
63 );\r
64\r
65//\r
66// Block I/O Protocol Interface\r
67//\r
68STATIC\r
69EFI_STATUS\r
70EFIAPI\r
71USBFloppyReset (\r
72 IN EFI_BLOCK_IO_PROTOCOL *This,\r
73 IN BOOLEAN ExtendedVerification\r
74 );\r
75\r
76STATIC\r
77EFI_STATUS\r
78EFIAPI\r
79USBFloppyReadBlocks (\r
80 IN EFI_BLOCK_IO_PROTOCOL *This,\r
81 IN UINT32 MediaId,\r
82 IN EFI_LBA LBA,\r
83 IN UINTN BufferSize,\r
84 OUT VOID *Buffer\r
85 );\r
86\r
87STATIC\r
88EFI_STATUS\r
89EFIAPI\r
90USBFloppyWriteBlocks (\r
91 IN EFI_BLOCK_IO_PROTOCOL *This,\r
92 IN UINT32 MediaId,\r
93 IN EFI_LBA LBA,\r
94 IN UINTN BufferSize,\r
95 IN VOID *Buffer\r
96 );\r
97\r
98STATIC\r
99EFI_STATUS\r
100EFIAPI\r
101USBFloppyFlushBlocks (\r
102 IN EFI_BLOCK_IO_PROTOCOL *This\r
103 );\r
104\r
105//\r
106// USB Floppy Driver Global Variables\r
107//\r
108EFI_DRIVER_BINDING_PROTOCOL gUSBFloppyDriverBinding = {\r
109 USBFloppyDriverBindingSupported,\r
110 USBFloppyDriverBindingStart,\r
111 USBFloppyDriverBindingStop,\r
61fb1657 112 0xa,\r
878ddf1f 113 NULL,\r
114 NULL\r
115};\r
116\r
117EFI_STATUS\r
118EFIAPI\r
119USBFloppyDriverBindingSupported (\r
120 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
121 IN EFI_HANDLE Controller,\r
122 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
123 )\r
124/*++\r
125\r
126 Routine Description:\r
127 Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
128 that has UsbHcProtocol installed will be supported.\r
129\r
130 Arguments:\r
131 This - Protocol instance pointer.\r
132 Controller - Handle of device to test\r
133 RemainingDevicePath - Not used\r
134\r
135 Returns:\r
136 EFI_SUCCESS - This driver supports this device.\r
137 EFI_UNSUPPORTED - This driver does not support this device.\r
138\r
139--*/\r
140{\r
141 EFI_STATUS OpenStatus;\r
142 EFI_USB_ATAPI_PROTOCOL *AtapiProtocol;\r
143\r
144 //\r
145 // check whether EFI_USB_ATAPI_PROTOCOL exists, if it does,\r
146 // then the controller must be a USB Mass Storage Controller\r
147 //\r
148 OpenStatus = gBS->OpenProtocol (\r
149 Controller,\r
150 &gEfiUsbAtapiProtocolGuid,\r
151 (VOID **) &AtapiProtocol,\r
152 This->DriverBindingHandle,\r
153 Controller,\r
154 EFI_OPEN_PROTOCOL_BY_DRIVER\r
155 );\r
156 if (EFI_ERROR (OpenStatus)) {\r
157 return OpenStatus;\r
158 }\r
159\r
160 gBS->CloseProtocol (\r
161 Controller,\r
162 &gEfiUsbAtapiProtocolGuid,\r
163 This->DriverBindingHandle,\r
164 Controller\r
165 );\r
166\r
167 return EFI_SUCCESS;\r
168}\r
169\r
170EFI_STATUS\r
171EFIAPI\r
172USBFloppyDriverBindingStart (\r
173 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
174 IN EFI_HANDLE Controller,\r
175 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
176 )\r
177/*++\r
178\r
179 Routine Description:\r
180 Starting the Usb Bus Driver\r
181\r
182 Arguments:\r
183 This - Protocol instance pointer.\r
184 Controller - Handle of device to test\r
185 RemainingDevicePath - Not used\r
186\r
187 Returns:\r
188 EFI_SUCCESS - This driver supports this device.\r
189 EFI_UNSUPPORTED - This driver does not support this device.\r
190 EFI_DEVICE_ERROR - This driver cannot be started due to device\r
191 Error\r
192 EFI_OUT_OF_RESOURCES- Can't allocate memory resources\r
193 EFI_ALREADY_STARTED - Thios driver has been started\r
194--*/\r
4d1fe68e 195{\r
196 EFI_STATUS Status;\r
878ddf1f 197 EFI_USB_ATAPI_PROTOCOL *AtapiProtocol;\r
198 USB_FLOPPY_DEV *UsbFloppyDevice;\r
4d1fe68e 199\r
878ddf1f 200 UsbFloppyDevice = NULL;\r
201 //\r
202 // Check whether Usb Atapi Protocol attached on the controller handle.\r
203 //\r
204 Status = gBS->OpenProtocol (\r
205 Controller,\r
206 &gEfiUsbAtapiProtocolGuid,\r
207 (VOID **) &AtapiProtocol,\r
208 This->DriverBindingHandle,\r
209 Controller,\r
210 EFI_OPEN_PROTOCOL_BY_DRIVER\r
211 );\r
212 if (EFI_ERROR (Status)) {\r
213 return Status;\r
214 }\r
215\r
216 Status = gBS->AllocatePool (\r
217 EfiBootServicesData,\r
218 sizeof (USB_FLOPPY_DEV),\r
219 (VOID **) &UsbFloppyDevice\r
220 );\r
221 if (EFI_ERROR (Status)) {\r
222 gBS->CloseProtocol (\r
223 Controller,\r
224 &gEfiUsbAtapiProtocolGuid,\r
225 This->DriverBindingHandle,\r
226 Controller\r
227 );\r
228 return Status;\r
229 }\r
230\r
231 ZeroMem (UsbFloppyDevice, sizeof (USB_FLOPPY_DEV));\r
232\r
233 UsbFloppyDevice->Handle = Controller;\r
234 UsbFloppyDevice->BlkIo.Media = &UsbFloppyDevice->BlkMedia;\r
235 UsbFloppyDevice->Signature = USB_FLOPPY_DEV_SIGNATURE;\r
236 UsbFloppyDevice->BlkIo.Reset = USBFloppyReset;\r
237 UsbFloppyDevice->BlkIo.ReadBlocks = USBFloppyReadBlocks;\r
238 UsbFloppyDevice->BlkIo.WriteBlocks = USBFloppyWriteBlocks;\r
239 UsbFloppyDevice->BlkIo.FlushBlocks = USBFloppyFlushBlocks;\r
240 UsbFloppyDevice->AtapiProtocol = AtapiProtocol;\r
241\r
242 //\r
243 // Identify drive type and retrieve media information.\r
244 //\r
245 Status = USBFloppyIdentify (UsbFloppyDevice);\r
246 if (EFI_ERROR (Status)) {\r
247 if (UsbFloppyDevice->SenseData != NULL) {\r
248 gBS->FreePool (UsbFloppyDevice->SenseData);\r
249 }\r
250\r
251 gBS->FreePool (UsbFloppyDevice);\r
252 gBS->CloseProtocol (\r
253 Controller,\r
254 &gEfiUsbAtapiProtocolGuid,\r
255 This->DriverBindingHandle,\r
256 Controller\r
257 );\r
258 return Status;\r
259 }\r
260 //\r
261 // Install Block I/O protocol for the usb floppy device.\r
262 //\r
263 Status = gBS->InstallProtocolInterface (\r
264 &Controller,\r
265 &gEfiBlockIoProtocolGuid,\r
266 EFI_NATIVE_INTERFACE,\r
267 &UsbFloppyDevice->BlkIo\r
268 );\r
269 if (EFI_ERROR (Status)) {\r
270 if (UsbFloppyDevice->SenseData != NULL) {\r
271 gBS->FreePool (UsbFloppyDevice->SenseData);\r
272 }\r
273\r
274 gBS->FreePool (UsbFloppyDevice);\r
275 gBS->CloseProtocol (\r
276 Controller,\r
277 &gEfiUsbAtapiProtocolGuid,\r
278 This->DriverBindingHandle,\r
279 Controller\r
280 );\r
281 return Status;\r
282 }\r
283\r
284 return EFI_SUCCESS;\r
285\r
286}\r
287\r
288\r
289EFI_STATUS\r
290EFIAPI\r
291USBFloppyDriverBindingStop (\r
292 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
293 IN EFI_HANDLE Controller,\r
294 IN UINTN NumberOfChildren,\r
295 IN EFI_HANDLE *ChildHandleBuffer\r
296 )\r
297/*++\r
298\r
299 Routine Description:\r
300 Stop this driver on ControllerHandle. Support stoping any child handles\r
301 created by this driver.\r
302\r
303 Arguments:\r
304 This - Protocol instance pointer.\r
305 Controller - Handle of device to stop driver on\r
306 NumberOfChildren - Number of Children in the ChildHandleBuffer\r
307 ChildHandleBuffer - List of handles for the children we need to stop.\r
308\r
309 Returns:\r
310 EFI_SUCCESS\r
311 EFI_DEVICE_ERROR\r
312 others\r
313\r
4d1fe68e 314--*/\r
878ddf1f 315{\r
316 EFI_STATUS Status;\r
317 USB_FLOPPY_DEV *UsbFloppyDevice;\r
318 EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
319\r
320 //\r
321 // First find USB_FLOPPY_DEV\r
322 //\r
323 gBS->OpenProtocol (\r
324 Controller,\r
325 &gEfiBlockIoProtocolGuid,\r
326 (VOID **) &BlkIo,\r
327 This->DriverBindingHandle,\r
328 Controller,\r
329 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
330 );\r
331\r
332 UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (BlkIo);\r
333\r
334 //\r
335 // Uninstall Block I/O protocol from the device handle\r
336 //\r
337 Status = gBS->UninstallProtocolInterface (\r
338 Controller,\r
339 &gEfiBlockIoProtocolGuid,\r
340 &UsbFloppyDevice->BlkIo\r
341 );\r
342 if (EFI_ERROR (Status)) {\r
343 return Status;\r
344 }\r
345 //\r
346 // Stop using EFI_USB_ATAPI_PROTOCOL\r
347 //\r
348 gBS->CloseProtocol (\r
349 Controller,\r
350 &gEfiUsbAtapiProtocolGuid,\r
351 This->DriverBindingHandle,\r
352 Controller\r
353 );\r
354\r
355 if (UsbFloppyDevice->SenseData != NULL) {\r
356 gBS->FreePool (UsbFloppyDevice->SenseData);\r
357 }\r
358\r
359 gBS->FreePool (UsbFloppyDevice);\r
360\r
361 return EFI_SUCCESS;\r
362}\r
363\r
364\r
365STATIC\r
366EFI_STATUS\r
367EFIAPI\r
368USBFloppyReset (\r
369 IN EFI_BLOCK_IO_PROTOCOL *This,\r
370 IN BOOLEAN ExtendedVerification\r
371 )\r
372/*++\r
373\r
374 Routine Description:\r
375 Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.\r
4d1fe68e 376\r
878ddf1f 377 Arguments:\r
378 This The EFI_BLOCK_IO_PROTOCOL instance.\r
379 ExtendedVerification\r
380 Indicates that the driver may perform a more exhaustive\r
381 verification operation of the device during reset.\r
382 (This parameter is ingored in this driver.)\r
4d1fe68e 383\r
384 Returns:\r
878ddf1f 385 EFI_SUCCESS - Success\r
4d1fe68e 386--*/\r
878ddf1f 387{\r
388 USB_FLOPPY_DEV *UsbFloppyDevice;\r
389 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;\r
390 EFI_STATUS Status;\r
391\r
392 UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);\r
393\r
394 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;\r
395\r
396 //\r
397 // directly calling EFI_USB_ATAPI_PROTOCOL.Reset() to implement reset.\r
398 //\r
4d1fe68e 399 Status = UsbAtapiInterface->UsbAtapiReset (UsbAtapiInterface, ExtendedVerification);\r
878ddf1f 400\r
401 return Status;\r
402}\r
403\r
404STATIC\r
405EFI_STATUS\r
406EFIAPI\r
407USBFloppyReadBlocks (\r
408 IN EFI_BLOCK_IO_PROTOCOL *This,\r
409 IN UINT32 MediaId,\r
410 IN EFI_LBA LBA,\r
411 IN UINTN BufferSize,\r
412 OUT VOID *Buffer\r
413 )\r
414/*++\r
415\r
416 Routine Description:\r
417 Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.\r
4d1fe68e 418\r
878ddf1f 419 Arguments:\r
420 This The EFI_BLOCK_IO_PROTOCOL instance.\r
421 MediaId The media id that the read request is for.\r
422 LBA The starting logical block address to read from on the device.\r
423 BufferSize\r
4d1fe68e 424 The size of the Buffer in bytes. This must be a multiple of\r
878ddf1f 425 the intrinsic block size of the device.\r
4d1fe68e 426 Buffer A pointer to the destination buffer for the data. The caller\r
878ddf1f 427 is responsible for either having implicit or explicit ownership\r
4d1fe68e 428 of the buffer.\r
429\r
430 Returns:\r
878ddf1f 431 EFI_INVALID_PARAMETER - Parameter is error\r
4d1fe68e 432 EFI_SUCCESS - Success\r
878ddf1f 433 EFI_DEVICE_ERROR - Hardware Error\r
434 EFI_NO_MEDIA - No media\r
435 EFI_MEDIA_CHANGED - Media Change\r
436 EFI_BAD_BUFFER_SIZE - Buffer size is bad\r
4d1fe68e 437 --*/\r
878ddf1f 438{\r
439 USB_FLOPPY_DEV *UsbFloppyDevice;\r
440 EFI_STATUS Status;\r
441 EFI_BLOCK_IO_MEDIA *Media;\r
442 UINTN BlockSize;\r
443 UINTN NumberOfBlocks;\r
444 BOOLEAN MediaChange;\r
878ddf1f 445\r
878ddf1f 446 Status = EFI_SUCCESS;\r
447 MediaChange = FALSE;\r
878ddf1f 448 UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);\r
449\r
450 //\r
451 // Check parameters\r
452 //\r
453 if (!Buffer) {\r
454 Status = EFI_INVALID_PARAMETER;\r
455 goto Done;\r
456 }\r
457\r
458 if (BufferSize == 0) {\r
459 Status = EFI_SUCCESS;\r
460 goto Done;\r
461 }\r
462\r
463 UsbFloppyTestUnitReady (UsbFloppyDevice);\r
464\r
465 Status = UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange);\r
466 if (EFI_ERROR (Status)) {\r
467\r
468 Status = EFI_DEVICE_ERROR;\r
469 goto Done;\r
470 }\r
471\r
472 if (MediaChange) {\r
878ddf1f 473 gBS->ReinstallProtocolInterface (\r
474 UsbFloppyDevice->Handle,\r
475 &gEfiBlockIoProtocolGuid,\r
476 &UsbFloppyDevice->BlkIo,\r
477 &UsbFloppyDevice->BlkIo\r
478 );\r
878ddf1f 479 }\r
480\r
481 Media = UsbFloppyDevice->BlkIo.Media;\r
482 BlockSize = Media->BlockSize;\r
483 NumberOfBlocks = BufferSize / BlockSize;\r
484\r
485 if (!(Media->MediaPresent)) {\r
486 Status = EFI_NO_MEDIA;\r
487 goto Done;\r
488 }\r
489\r
490 if (MediaId != Media->MediaId) {\r
491 Status = EFI_MEDIA_CHANGED;\r
492 goto Done;\r
493 }\r
494\r
495 if (BufferSize % BlockSize != 0) {\r
496 Status = EFI_BAD_BUFFER_SIZE;\r
497 goto Done;\r
498 }\r
499\r
500 if (LBA > Media->LastBlock) {\r
501 Status = EFI_INVALID_PARAMETER;\r
502 goto Done;\r
503 }\r
504\r
505 if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {\r
506 Status = EFI_INVALID_PARAMETER;\r
507 goto Done;\r
508 }\r
509\r
510 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {\r
511 Status = EFI_INVALID_PARAMETER;\r
512 goto Done;\r
513 }\r
514\r
4d1fe68e 515 while (NumberOfBlocks > 0) {\r
878ddf1f 516\r
4d1fe68e 517 if (NumberOfBlocks > BLOCK_UNIT) {\r
518 Status = USBFloppyRead10 (UsbFloppyDevice, Buffer, LBA, BLOCK_UNIT);\r
519 } else {\r
520 Status = USBFloppyRead10 (UsbFloppyDevice, Buffer, LBA, NumberOfBlocks);\r
878ddf1f 521 }\r
522\r
878ddf1f 523 if (EFI_ERROR (Status)) {\r
524 This->Reset (This, TRUE);\r
525 Status = EFI_DEVICE_ERROR;\r
526 }\r
878ddf1f 527\r
4d1fe68e 528 if (NumberOfBlocks > BLOCK_UNIT) {\r
529 NumberOfBlocks -= BLOCK_UNIT;\r
530 LBA += BLOCK_UNIT;\r
531 Buffer = (UINT8 *) Buffer + This->Media->BlockSize * BLOCK_UNIT;\r
532 } else {\r
533 NumberOfBlocks -= NumberOfBlocks;\r
534 LBA += NumberOfBlocks;\r
535 Buffer = (UINT8 *) Buffer + This->Media->BlockSize * NumberOfBlocks;\r
536 }\r
537 }\r
538\r
539 Done:\r
878ddf1f 540 return Status;\r
541}\r
542\r
543STATIC\r
544EFI_STATUS\r
545EFIAPI\r
546USBFloppyWriteBlocks (\r
547 IN EFI_BLOCK_IO_PROTOCOL *This,\r
548 IN UINT32 MediaId,\r
549 IN EFI_LBA LBA,\r
550 IN UINTN BufferSize,\r
551 IN VOID *Buffer\r
552 )\r
553/*++\r
554\r
555 Routine Description:\r
556 Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.\r
4d1fe68e 557\r
878ddf1f 558 Arguments:\r
559 This The EFI_BLOCK_IO_PROTOCOL instance.\r
560 MediaId The media id that the write request is for.\r
561 LBA The starting logical block address to be written.\r
4d1fe68e 562 The caller is responsible for writing to only\r
878ddf1f 563 legitimate locations.\r
564 BufferSize\r
4d1fe68e 565 The size of the Buffer in bytes. This must be a multiple of\r
878ddf1f 566 the intrinsic block size of the device.\r
4d1fe68e 567 Buffer A pointer to the source buffer for the data. The caller\r
878ddf1f 568 is responsible for either having implicit or explicit ownership\r
4d1fe68e 569 of the buffer.\r
570\r
571 Returns:\r
878ddf1f 572 EFI_INVALID_PARAMETER - Parameter is error\r
4d1fe68e 573 EFI_SUCCESS - Success\r
878ddf1f 574 EFI_DEVICE_ERROR - Hardware Error\r
575 EFI_NO_MEDIA - No media\r
576 EFI_MEDIA_CHANGED - Media Change\r
577 EFI_BAD_BUFFER_SIZE - Buffer size is bad\r
578\r
4d1fe68e 579--*/\r
878ddf1f 580{\r
581 USB_FLOPPY_DEV *UsbFloppyDevice;\r
582 EFI_STATUS Status;\r
583 EFI_BLOCK_IO_MEDIA *Media;\r
584 UINTN BlockSize;\r
585 UINTN NumberOfBlocks;\r
586 BOOLEAN MediaChange;\r
878ddf1f 587\r
878ddf1f 588 Status = EFI_SUCCESS;\r
589 MediaChange = FALSE;\r
878ddf1f 590\r
591 UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);\r
592\r
593 //\r
594 // Check parameters\r
595 //\r
596 if (!Buffer) {\r
597 Status = EFI_INVALID_PARAMETER;\r
598 goto Done;\r
599 }\r
600\r
601 if (BufferSize == 0) {\r
602 Status = EFI_SUCCESS;\r
603 goto Done;\r
604 }\r
605\r
606 UsbFloppyTestUnitReady (UsbFloppyDevice);\r
607\r
608 Status = UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange);\r
609 if (EFI_ERROR (Status)) {\r
610\r
611 Status = EFI_DEVICE_ERROR;\r
612 goto Done;\r
613 }\r
614\r
615 if (MediaChange) {\r
878ddf1f 616 gBS->ReinstallProtocolInterface (\r
617 UsbFloppyDevice->Handle,\r
618 &gEfiBlockIoProtocolGuid,\r
619 &UsbFloppyDevice->BlkIo,\r
620 &UsbFloppyDevice->BlkIo\r
621 );\r
878ddf1f 622 }\r
623\r
624 Media = UsbFloppyDevice->BlkIo.Media;\r
625 BlockSize = Media->BlockSize;\r
626 NumberOfBlocks = BufferSize / BlockSize;\r
627\r
628 if (!(Media->MediaPresent)) {\r
629 Status = EFI_NO_MEDIA;\r
630 goto Done;\r
631 }\r
632\r
633 if (MediaId != Media->MediaId) {\r
634 Status = EFI_MEDIA_CHANGED;\r
635 goto Done;\r
636 }\r
637\r
638 if (BufferSize % BlockSize != 0) {\r
639 Status = EFI_BAD_BUFFER_SIZE;\r
640 goto Done;\r
641 }\r
642\r
643 if (LBA > Media->LastBlock) {\r
644 Status = EFI_INVALID_PARAMETER;\r
645 goto Done;\r
646 }\r
647\r
648 if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {\r
649 Status = EFI_INVALID_PARAMETER;\r
650 goto Done;\r
651 }\r
652\r
653 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {\r
654 Status = EFI_INVALID_PARAMETER;\r
655 goto Done;\r
656 }\r
657\r
658 if (UsbFloppyDevice->BlkMedia.ReadOnly) {\r
659 Status = EFI_WRITE_PROTECTED;\r
660 goto Done;\r
661 }\r
662\r
4d1fe68e 663 while (NumberOfBlocks > 0) {\r
878ddf1f 664\r
4d1fe68e 665 if (NumberOfBlocks > BLOCK_UNIT) {\r
666 Status = USBFloppyWrite10 (UsbFloppyDevice, Buffer, LBA, BLOCK_UNIT);\r
667 } else {\r
668 Status = USBFloppyWrite10 (UsbFloppyDevice, Buffer, LBA, NumberOfBlocks);\r
878ddf1f 669 }\r
670\r
878ddf1f 671 if (EFI_ERROR (Status)) {\r
672 This->Reset (This, TRUE);\r
673 Status = EFI_DEVICE_ERROR;\r
674 }\r
4d1fe68e 675\r
676 if (NumberOfBlocks > BLOCK_UNIT) {\r
677 NumberOfBlocks -= BLOCK_UNIT;\r
678 LBA += BLOCK_UNIT;\r
679 Buffer = (UINT8 *) Buffer + This->Media->BlockSize * BLOCK_UNIT;\r
680 } else {\r
681 NumberOfBlocks -= NumberOfBlocks;\r
682 LBA += NumberOfBlocks;\r
683 Buffer = (UINT8 *) Buffer + This->Media->BlockSize * NumberOfBlocks;\r
684 }\r
685 }\r
878ddf1f 686\r
687Done:\r
4d1fe68e 688\r
878ddf1f 689 return Status;\r
690}\r
691\r
692STATIC\r
693EFI_STATUS\r
694EFIAPI\r
695USBFloppyFlushBlocks (\r
696 IN EFI_BLOCK_IO_PROTOCOL *This\r
697 )\r
698/*++\r
699\r
700 Routine Description:\r
701 Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.\r
702 (In this driver, this function just returns EFI_SUCCESS.)\r
4d1fe68e 703\r
878ddf1f 704 Arguments:\r
705 This The EFI_BLOCK_IO_PROTOCOL instance.\r
4d1fe68e 706\r
707 Returns:\r
878ddf1f 708 EFI_SUCCESS - Success\r
4d1fe68e 709--*/\r
878ddf1f 710{\r
711 return EFI_SUCCESS;\r
712}\r