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