3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 USB Mass Storage Driver
24 #include "UsbMassStorage.h"
25 #include "UsbMassStorageHelper.h"
28 // Block I/O Protocol Interface
34 IN EFI_BLOCK_IO_PROTOCOL
*This
,
35 IN BOOLEAN ExtendedVerification
42 IN EFI_BLOCK_IO_PROTOCOL
*This
,
52 USBFloppyWriteBlocks (
53 IN EFI_BLOCK_IO_PROTOCOL
*This
,
63 USBFloppyFlushBlocks (
64 IN EFI_BLOCK_IO_PROTOCOL
*This
68 // USB Floppy Driver Global Variables
70 EFI_DRIVER_BINDING_PROTOCOL gUSBFloppyDriverBinding
= {
71 USBFloppyDriverBindingSupported
,
72 USBFloppyDriverBindingStart
,
73 USBFloppyDriverBindingStop
,
81 USBFloppyDriverBindingSupported (
82 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
83 IN EFI_HANDLE Controller
,
84 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
89 Test to see if this driver supports ControllerHandle. Any ControllerHandle
90 that has UsbHcProtocol installed will be supported.
93 This - Protocol instance pointer.
94 Controller - Handle of device to test
95 RemainingDevicePath - Not used
98 EFI_SUCCESS - This driver supports this device.
99 EFI_UNSUPPORTED - This driver does not support this device.
103 EFI_STATUS OpenStatus
;
104 EFI_USB_ATAPI_PROTOCOL
*AtapiProtocol
;
107 // check whether EFI_USB_ATAPI_PROTOCOL exists, if it does,
108 // then the controller must be a USB Mass Storage Controller
110 OpenStatus
= gBS
->OpenProtocol (
112 &gEfiUsbAtapiProtocolGuid
,
113 (VOID
**) &AtapiProtocol
,
114 This
->DriverBindingHandle
,
116 EFI_OPEN_PROTOCOL_BY_DRIVER
118 if (EFI_ERROR (OpenStatus
)) {
124 &gEfiUsbAtapiProtocolGuid
,
125 This
->DriverBindingHandle
,
134 USBFloppyDriverBindingStart (
135 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
136 IN EFI_HANDLE Controller
,
137 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
142 Starting the Usb Bus Driver
145 This - Protocol instance pointer.
146 Controller - Handle of device to test
147 RemainingDevicePath - Not used
150 EFI_SUCCESS - This driver supports this device.
151 EFI_UNSUPPORTED - This driver does not support this device.
152 EFI_DEVICE_ERROR - This driver cannot be started due to device
154 EFI_OUT_OF_RESOURCES- Can't allocate memory resources
155 EFI_ALREADY_STARTED - Thios driver has been started
159 EFI_USB_ATAPI_PROTOCOL
*AtapiProtocol
;
160 USB_FLOPPY_DEV
*UsbFloppyDevice
;
162 UsbFloppyDevice
= NULL
;
164 // Check whether Usb Atapi Protocol attached on the controller handle.
166 Status
= gBS
->OpenProtocol (
168 &gEfiUsbAtapiProtocolGuid
,
169 (VOID
**) &AtapiProtocol
,
170 This
->DriverBindingHandle
,
172 EFI_OPEN_PROTOCOL_BY_DRIVER
174 if (EFI_ERROR (Status
)) {
178 Status
= gBS
->AllocatePool (
180 sizeof (USB_FLOPPY_DEV
),
181 (VOID
**) &UsbFloppyDevice
183 if (EFI_ERROR (Status
)) {
186 &gEfiUsbAtapiProtocolGuid
,
187 This
->DriverBindingHandle
,
193 ZeroMem (UsbFloppyDevice
, sizeof (USB_FLOPPY_DEV
));
195 UsbFloppyDevice
->Handle
= Controller
;
196 UsbFloppyDevice
->BlkIo
.Media
= &UsbFloppyDevice
->BlkMedia
;
197 UsbFloppyDevice
->Signature
= USB_FLOPPY_DEV_SIGNATURE
;
198 UsbFloppyDevice
->BlkIo
.Reset
= USBFloppyReset
;
199 UsbFloppyDevice
->BlkIo
.ReadBlocks
= USBFloppyReadBlocks
;
200 UsbFloppyDevice
->BlkIo
.WriteBlocks
= USBFloppyWriteBlocks
;
201 UsbFloppyDevice
->BlkIo
.FlushBlocks
= USBFloppyFlushBlocks
;
202 UsbFloppyDevice
->AtapiProtocol
= AtapiProtocol
;
205 // Identify drive type and retrieve media information.
207 Status
= USBFloppyIdentify (UsbFloppyDevice
);
208 if (EFI_ERROR (Status
)) {
209 if (UsbFloppyDevice
->SenseData
!= NULL
) {
210 gBS
->FreePool (UsbFloppyDevice
->SenseData
);
213 gBS
->FreePool (UsbFloppyDevice
);
216 &gEfiUsbAtapiProtocolGuid
,
217 This
->DriverBindingHandle
,
223 // Install Block I/O protocol for the usb floppy device.
225 Status
= gBS
->InstallProtocolInterface (
227 &gEfiBlockIoProtocolGuid
,
228 EFI_NATIVE_INTERFACE
,
229 &UsbFloppyDevice
->BlkIo
231 if (EFI_ERROR (Status
)) {
232 if (UsbFloppyDevice
->SenseData
!= NULL
) {
233 gBS
->FreePool (UsbFloppyDevice
->SenseData
);
236 gBS
->FreePool (UsbFloppyDevice
);
239 &gEfiUsbAtapiProtocolGuid
,
240 This
->DriverBindingHandle
,
253 USBFloppyDriverBindingStop (
254 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
255 IN EFI_HANDLE Controller
,
256 IN UINTN NumberOfChildren
,
257 IN EFI_HANDLE
*ChildHandleBuffer
262 Stop this driver on ControllerHandle. Support stoping any child handles
263 created by this driver.
266 This - Protocol instance pointer.
267 Controller - Handle of device to stop driver on
268 NumberOfChildren - Number of Children in the ChildHandleBuffer
269 ChildHandleBuffer - List of handles for the children we need to stop.
279 USB_FLOPPY_DEV
*UsbFloppyDevice
;
280 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
283 // First find USB_FLOPPY_DEV
287 &gEfiBlockIoProtocolGuid
,
289 This
->DriverBindingHandle
,
291 EFI_OPEN_PROTOCOL_GET_PROTOCOL
294 UsbFloppyDevice
= USB_FLOPPY_DEV_FROM_THIS (BlkIo
);
297 // Uninstall Block I/O protocol from the device handle
299 Status
= gBS
->UninstallProtocolInterface (
301 &gEfiBlockIoProtocolGuid
,
302 &UsbFloppyDevice
->BlkIo
304 if (EFI_ERROR (Status
)) {
308 // Stop using EFI_USB_ATAPI_PROTOCOL
312 &gEfiUsbAtapiProtocolGuid
,
313 This
->DriverBindingHandle
,
317 if (UsbFloppyDevice
->SenseData
!= NULL
) {
318 gBS
->FreePool (UsbFloppyDevice
->SenseData
);
321 gBS
->FreePool (UsbFloppyDevice
);
331 IN EFI_BLOCK_IO_PROTOCOL
*This
,
332 IN BOOLEAN ExtendedVerification
337 Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
340 This The EFI_BLOCK_IO_PROTOCOL instance.
342 Indicates that the driver may perform a more exhaustive
343 verification operation of the device during reset.
344 (This parameter is ingored in this driver.)
347 EFI_SUCCESS - Success
350 USB_FLOPPY_DEV
*UsbFloppyDevice
;
351 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
355 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
357 UsbFloppyDevice
= USB_FLOPPY_DEV_FROM_THIS (This
);
359 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
362 // directly calling EFI_USB_ATAPI_PROTOCOL.Reset() to implement reset.
364 Status
= UsbAtapiInterface
->UsbAtapiReset (UsbAtapiInterface
, ExtendedVerification
);
366 gBS
->RestoreTPL (OldTpl
);
374 USBFloppyReadBlocks (
375 IN EFI_BLOCK_IO_PROTOCOL
*This
,
384 Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
387 This The EFI_BLOCK_IO_PROTOCOL instance.
388 MediaId The media id that the read request is for.
389 LBA The starting logical block address to read from on the device.
391 The size of the Buffer in bytes. This must be a multiple of
392 the intrinsic block size of the device.
393 Buffer A pointer to the destination buffer for the data. The caller
394 is responsible for either having implicit or explicit ownership
398 EFI_INVALID_PARAMETER - Parameter is error
399 EFI_SUCCESS - Success
400 EFI_DEVICE_ERROR - Hardware Error
401 EFI_NO_MEDIA - No media
402 EFI_MEDIA_CHANGED - Media Change
403 EFI_BAD_BUFFER_SIZE - Buffer size is bad
406 USB_FLOPPY_DEV
*UsbFloppyDevice
;
408 EFI_BLOCK_IO_MEDIA
*Media
;
410 UINTN NumberOfBlocks
;
414 Status
= EFI_SUCCESS
;
416 UsbFloppyDevice
= USB_FLOPPY_DEV_FROM_THIS (This
);
421 if (Buffer
== NULL
) {
422 return EFI_INVALID_PARAMETER
;
425 if (BufferSize
== 0) {
429 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
431 UsbFloppyTestUnitReady (UsbFloppyDevice
);
433 Status
= UsbFloppyDetectMedia (UsbFloppyDevice
, &MediaChange
);
434 if (EFI_ERROR (Status
)) {
436 Status
= EFI_DEVICE_ERROR
;
441 gBS
->ReinstallProtocolInterface (
442 UsbFloppyDevice
->Handle
,
443 &gEfiBlockIoProtocolGuid
,
444 &UsbFloppyDevice
->BlkIo
,
445 &UsbFloppyDevice
->BlkIo
449 Media
= UsbFloppyDevice
->BlkIo
.Media
;
450 BlockSize
= Media
->BlockSize
;
451 NumberOfBlocks
= BufferSize
/ BlockSize
;
453 if (!(Media
->MediaPresent
)) {
454 Status
= EFI_NO_MEDIA
;
458 if (MediaId
!= Media
->MediaId
) {
459 Status
= EFI_MEDIA_CHANGED
;
463 if (BufferSize
% BlockSize
!= 0) {
464 Status
= EFI_BAD_BUFFER_SIZE
;
468 if (LBA
> Media
->LastBlock
) {
469 Status
= EFI_INVALID_PARAMETER
;
473 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
474 Status
= EFI_INVALID_PARAMETER
;
478 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
479 Status
= EFI_INVALID_PARAMETER
;
483 while (NumberOfBlocks
> 0) {
485 if (NumberOfBlocks
> BLOCK_UNIT
) {
486 Status
= USBFloppyRead10 (UsbFloppyDevice
, Buffer
, LBA
, BLOCK_UNIT
);
488 Status
= USBFloppyRead10 (UsbFloppyDevice
, Buffer
, LBA
, NumberOfBlocks
);
491 if (EFI_ERROR (Status
)) {
492 This
->Reset (This
, TRUE
);
493 Status
= EFI_DEVICE_ERROR
;
497 if (NumberOfBlocks
> BLOCK_UNIT
) {
498 NumberOfBlocks
-= BLOCK_UNIT
;
500 Buffer
= (UINT8
*) Buffer
+ This
->Media
->BlockSize
* BLOCK_UNIT
;
502 NumberOfBlocks
-= NumberOfBlocks
;
503 LBA
+= NumberOfBlocks
;
504 Buffer
= (UINT8
*) Buffer
+ This
->Media
->BlockSize
* NumberOfBlocks
;
509 gBS
->RestoreTPL (OldTpl
);
516 USBFloppyWriteBlocks (
517 IN EFI_BLOCK_IO_PROTOCOL
*This
,
526 Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
529 This The EFI_BLOCK_IO_PROTOCOL instance.
530 MediaId The media id that the write request is for.
531 LBA The starting logical block address to be written.
532 The caller is responsible for writing to only
533 legitimate locations.
535 The size of the Buffer in bytes. This must be a multiple of
536 the intrinsic block size of the device.
537 Buffer A pointer to the source buffer for the data. The caller
538 is responsible for either having implicit or explicit ownership
542 EFI_INVALID_PARAMETER - Parameter is error
543 EFI_SUCCESS - Success
544 EFI_DEVICE_ERROR - Hardware Error
545 EFI_NO_MEDIA - No media
546 EFI_MEDIA_CHANGED - Media Change
547 EFI_BAD_BUFFER_SIZE - Buffer size is bad
551 USB_FLOPPY_DEV
*UsbFloppyDevice
;
553 EFI_BLOCK_IO_MEDIA
*Media
;
555 UINTN NumberOfBlocks
;
559 Status
= EFI_SUCCESS
;
562 UsbFloppyDevice
= USB_FLOPPY_DEV_FROM_THIS (This
);
567 if (Buffer
== NULL
) {
568 return EFI_INVALID_PARAMETER
;
571 if (BufferSize
== 0) {
575 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
577 UsbFloppyTestUnitReady (UsbFloppyDevice
);
579 Status
= UsbFloppyDetectMedia (UsbFloppyDevice
, &MediaChange
);
580 if (EFI_ERROR (Status
)) {
582 Status
= EFI_DEVICE_ERROR
;
587 gBS
->ReinstallProtocolInterface (
588 UsbFloppyDevice
->Handle
,
589 &gEfiBlockIoProtocolGuid
,
590 &UsbFloppyDevice
->BlkIo
,
591 &UsbFloppyDevice
->BlkIo
595 Media
= UsbFloppyDevice
->BlkIo
.Media
;
596 BlockSize
= Media
->BlockSize
;
597 NumberOfBlocks
= BufferSize
/ BlockSize
;
599 if (!(Media
->MediaPresent
)) {
600 Status
= EFI_NO_MEDIA
;
604 if (MediaId
!= Media
->MediaId
) {
605 Status
= EFI_MEDIA_CHANGED
;
609 if (BufferSize
% BlockSize
!= 0) {
610 Status
= EFI_BAD_BUFFER_SIZE
;
614 if (LBA
> Media
->LastBlock
) {
615 Status
= EFI_INVALID_PARAMETER
;
619 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
620 Status
= EFI_INVALID_PARAMETER
;
624 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
625 Status
= EFI_INVALID_PARAMETER
;
629 if (UsbFloppyDevice
->BlkMedia
.ReadOnly
) {
630 Status
= EFI_WRITE_PROTECTED
;
634 while (NumberOfBlocks
> 0) {
636 if (NumberOfBlocks
> BLOCK_UNIT
) {
637 Status
= USBFloppyWrite10 (UsbFloppyDevice
, Buffer
, LBA
, BLOCK_UNIT
);
639 Status
= USBFloppyWrite10 (UsbFloppyDevice
, Buffer
, LBA
, NumberOfBlocks
);
642 if (EFI_ERROR (Status
)) {
643 This
->Reset (This
, TRUE
);
644 Status
= EFI_DEVICE_ERROR
;
648 if (NumberOfBlocks
> BLOCK_UNIT
) {
649 NumberOfBlocks
-= BLOCK_UNIT
;
651 Buffer
= (UINT8
*) Buffer
+ This
->Media
->BlockSize
* BLOCK_UNIT
;
653 NumberOfBlocks
-= NumberOfBlocks
;
654 LBA
+= NumberOfBlocks
;
655 Buffer
= (UINT8
*) Buffer
+ This
->Media
->BlockSize
* NumberOfBlocks
;
660 gBS
->RestoreTPL (OldTpl
);
667 USBFloppyFlushBlocks (
668 IN EFI_BLOCK_IO_PROTOCOL
*This
673 Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
674 (In this driver, this function just returns EFI_SUCCESS.)
677 This The EFI_BLOCK_IO_PROTOCOL instance.
680 EFI_SUCCESS - Success