3 Copyright (c) 2006, 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"
27 extern EFI_COMPONENT_NAME_PROTOCOL gUsbMassStorageComponentName
;
31 // Driver model protocol interface
35 USBMassStorageDriverBindingEntryPoint (
36 IN EFI_HANDLE ImageHandle
,
37 IN EFI_SYSTEM_TABLE
*SystemTable
42 USBFloppyDriverBindingSupported (
43 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
44 IN EFI_HANDLE Controller
,
45 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
50 USBFloppyDriverBindingStart (
51 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
52 IN EFI_HANDLE Controller
,
53 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
58 USBFloppyDriverBindingStop (
59 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
60 IN EFI_HANDLE Controller
,
61 IN UINTN NumberOfChildren
,
62 IN EFI_HANDLE
*ChildHandleBuffer
66 // Block I/O Protocol Interface
72 IN EFI_BLOCK_IO_PROTOCOL
*This
,
73 IN BOOLEAN ExtendedVerification
80 IN EFI_BLOCK_IO_PROTOCOL
*This
,
90 USBFloppyWriteBlocks (
91 IN EFI_BLOCK_IO_PROTOCOL
*This
,
101 USBFloppyFlushBlocks (
102 IN EFI_BLOCK_IO_PROTOCOL
*This
106 // USB Floppy Driver Global Variables
108 EFI_DRIVER_BINDING_PROTOCOL gUSBFloppyDriverBinding
= {
109 USBFloppyDriverBindingSupported
,
110 USBFloppyDriverBindingStart
,
111 USBFloppyDriverBindingStop
,
119 USBFloppyDriverBindingSupported (
120 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
121 IN EFI_HANDLE Controller
,
122 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
127 Test to see if this driver supports ControllerHandle. Any ControllerHandle
128 that has UsbHcProtocol installed will be supported.
131 This - Protocol instance pointer.
132 Controller - Handle of device to test
133 RemainingDevicePath - Not used
136 EFI_SUCCESS - This driver supports this device.
137 EFI_UNSUPPORTED - This driver does not support this device.
141 EFI_STATUS OpenStatus
;
142 EFI_USB_ATAPI_PROTOCOL
*AtapiProtocol
;
145 // check whether EFI_USB_ATAPI_PROTOCOL exists, if it does,
146 // then the controller must be a USB Mass Storage Controller
148 OpenStatus
= gBS
->OpenProtocol (
150 &gEfiUsbAtapiProtocolGuid
,
151 (VOID
**) &AtapiProtocol
,
152 This
->DriverBindingHandle
,
154 EFI_OPEN_PROTOCOL_BY_DRIVER
156 if (EFI_ERROR (OpenStatus
)) {
162 &gEfiUsbAtapiProtocolGuid
,
163 This
->DriverBindingHandle
,
172 USBFloppyDriverBindingStart (
173 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
174 IN EFI_HANDLE Controller
,
175 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
180 Starting the Usb Bus Driver
183 This - Protocol instance pointer.
184 Controller - Handle of device to test
185 RemainingDevicePath - Not used
188 EFI_SUCCESS - This driver supports this device.
189 EFI_UNSUPPORTED - This driver does not support this device.
190 EFI_DEVICE_ERROR - This driver cannot be started due to device
192 EFI_OUT_OF_RESOURCES- Can't allocate memory resources
193 EFI_ALREADY_STARTED - Thios driver has been started
197 EFI_USB_ATAPI_PROTOCOL
*AtapiProtocol
;
198 USB_FLOPPY_DEV
*UsbFloppyDevice
;
200 UsbFloppyDevice
= NULL
;
202 // Check whether Usb Atapi Protocol attached on the controller handle.
204 Status
= gBS
->OpenProtocol (
206 &gEfiUsbAtapiProtocolGuid
,
207 (VOID
**) &AtapiProtocol
,
208 This
->DriverBindingHandle
,
210 EFI_OPEN_PROTOCOL_BY_DRIVER
212 if (EFI_ERROR (Status
)) {
216 Status
= gBS
->AllocatePool (
218 sizeof (USB_FLOPPY_DEV
),
219 (VOID
**) &UsbFloppyDevice
221 if (EFI_ERROR (Status
)) {
224 &gEfiUsbAtapiProtocolGuid
,
225 This
->DriverBindingHandle
,
231 ZeroMem (UsbFloppyDevice
, sizeof (USB_FLOPPY_DEV
));
233 UsbFloppyDevice
->Handle
= Controller
;
234 UsbFloppyDevice
->BlkIo
.Media
= &UsbFloppyDevice
->BlkMedia
;
235 UsbFloppyDevice
->Signature
= USB_FLOPPY_DEV_SIGNATURE
;
236 UsbFloppyDevice
->BlkIo
.Reset
= USBFloppyReset
;
237 UsbFloppyDevice
->BlkIo
.ReadBlocks
= USBFloppyReadBlocks
;
238 UsbFloppyDevice
->BlkIo
.WriteBlocks
= USBFloppyWriteBlocks
;
239 UsbFloppyDevice
->BlkIo
.FlushBlocks
= USBFloppyFlushBlocks
;
240 UsbFloppyDevice
->AtapiProtocol
= AtapiProtocol
;
243 // Identify drive type and retrieve media information.
245 Status
= USBFloppyIdentify (UsbFloppyDevice
);
246 if (EFI_ERROR (Status
)) {
247 if (UsbFloppyDevice
->SenseData
!= NULL
) {
248 gBS
->FreePool (UsbFloppyDevice
->SenseData
);
251 gBS
->FreePool (UsbFloppyDevice
);
254 &gEfiUsbAtapiProtocolGuid
,
255 This
->DriverBindingHandle
,
261 // Install Block I/O protocol for the usb floppy device.
263 Status
= gBS
->InstallProtocolInterface (
265 &gEfiBlockIoProtocolGuid
,
266 EFI_NATIVE_INTERFACE
,
267 &UsbFloppyDevice
->BlkIo
269 if (EFI_ERROR (Status
)) {
270 if (UsbFloppyDevice
->SenseData
!= NULL
) {
271 gBS
->FreePool (UsbFloppyDevice
->SenseData
);
274 gBS
->FreePool (UsbFloppyDevice
);
277 &gEfiUsbAtapiProtocolGuid
,
278 This
->DriverBindingHandle
,
291 USBFloppyDriverBindingStop (
292 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
293 IN EFI_HANDLE Controller
,
294 IN UINTN NumberOfChildren
,
295 IN EFI_HANDLE
*ChildHandleBuffer
300 Stop this driver on ControllerHandle. Support stoping any child handles
301 created by this driver.
304 This - Protocol instance pointer.
305 Controller - Handle of device to stop driver on
306 NumberOfChildren - Number of Children in the ChildHandleBuffer
307 ChildHandleBuffer - List of handles for the children we need to stop.
317 USB_FLOPPY_DEV
*UsbFloppyDevice
;
318 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
321 // First find USB_FLOPPY_DEV
325 &gEfiBlockIoProtocolGuid
,
327 This
->DriverBindingHandle
,
329 EFI_OPEN_PROTOCOL_GET_PROTOCOL
332 UsbFloppyDevice
= USB_FLOPPY_DEV_FROM_THIS (BlkIo
);
335 // Uninstall Block I/O protocol from the device handle
337 Status
= gBS
->UninstallProtocolInterface (
339 &gEfiBlockIoProtocolGuid
,
340 &UsbFloppyDevice
->BlkIo
342 if (EFI_ERROR (Status
)) {
346 // Stop using EFI_USB_ATAPI_PROTOCOL
350 &gEfiUsbAtapiProtocolGuid
,
351 This
->DriverBindingHandle
,
355 if (UsbFloppyDevice
->SenseData
!= NULL
) {
356 gBS
->FreePool (UsbFloppyDevice
->SenseData
);
359 gBS
->FreePool (UsbFloppyDevice
);
369 IN EFI_BLOCK_IO_PROTOCOL
*This
,
370 IN BOOLEAN ExtendedVerification
375 Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
378 This The EFI_BLOCK_IO_PROTOCOL instance.
380 Indicates that the driver may perform a more exhaustive
381 verification operation of the device during reset.
382 (This parameter is ingored in this driver.)
385 EFI_SUCCESS - Success
388 USB_FLOPPY_DEV
*UsbFloppyDevice
;
389 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
392 UsbFloppyDevice
= USB_FLOPPY_DEV_FROM_THIS (This
);
394 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
397 // directly calling EFI_USB_ATAPI_PROTOCOL.Reset() to implement reset.
399 Status
= UsbAtapiInterface
->UsbAtapiReset (UsbAtapiInterface
, TRUE
);
407 USBFloppyReadBlocks (
408 IN EFI_BLOCK_IO_PROTOCOL
*This
,
417 Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
420 This The EFI_BLOCK_IO_PROTOCOL instance.
421 MediaId The media id that the read request is for.
422 LBA The starting logical block address to read from on the device.
424 The size of the Buffer in bytes. This must be a multiple of
425 the intrinsic block size of the device.
426 Buffer A pointer to the destination buffer for the data. The caller
427 is responsible for either having implicit or explicit ownership
431 EFI_INVALID_PARAMETER - Parameter is error
432 EFI_SUCCESS - Success
433 EFI_DEVICE_ERROR - Hardware Error
434 EFI_NO_MEDIA - No media
435 EFI_MEDIA_CHANGED - Media Change
436 EFI_BAD_BUFFER_SIZE - Buffer size is bad
439 USB_FLOPPY_DEV
*UsbFloppyDevice
;
441 EFI_BLOCK_IO_MEDIA
*Media
;
443 UINTN NumberOfBlocks
;
448 OldTpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
449 Status
= EFI_SUCCESS
;
453 UsbFloppyDevice
= USB_FLOPPY_DEV_FROM_THIS (This
);
459 Status
= EFI_INVALID_PARAMETER
;
463 if (BufferSize
== 0) {
464 Status
= EFI_SUCCESS
;
468 UsbFloppyTestUnitReady (UsbFloppyDevice
);
470 Status
= UsbFloppyDetectMedia (UsbFloppyDevice
, &MediaChange
);
471 if (EFI_ERROR (Status
)) {
473 Status
= EFI_DEVICE_ERROR
;
478 gBS
->RestoreTPL (OldTpl
);
479 gBS
->ReinstallProtocolInterface (
480 UsbFloppyDevice
->Handle
,
481 &gEfiBlockIoProtocolGuid
,
482 &UsbFloppyDevice
->BlkIo
,
483 &UsbFloppyDevice
->BlkIo
485 gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
488 Media
= UsbFloppyDevice
->BlkIo
.Media
;
489 BlockSize
= Media
->BlockSize
;
490 NumberOfBlocks
= BufferSize
/ BlockSize
;
492 if (!(Media
->MediaPresent
)) {
493 Status
= EFI_NO_MEDIA
;
497 if (MediaId
!= Media
->MediaId
) {
498 Status
= EFI_MEDIA_CHANGED
;
502 if (BufferSize
% BlockSize
!= 0) {
503 Status
= EFI_BAD_BUFFER_SIZE
;
507 if (LBA
> Media
->LastBlock
) {
508 Status
= EFI_INVALID_PARAMETER
;
512 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
513 Status
= EFI_INVALID_PARAMETER
;
517 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
518 Status
= EFI_INVALID_PARAMETER
;
522 if (!EFI_ERROR (Status
)) {
524 Status
= USBFloppyRead10 (UsbFloppyDevice
, Buffer
, LBA
, 1);
525 if (EFI_ERROR (Status
)) {
526 This
->Reset (This
, TRUE
);
527 Status
= EFI_DEVICE_ERROR
;
533 Buffer
= (UINT8
*) Buffer
+ This
->Media
->BlockSize
;
535 if (NumberOfBlocks
== 0) {
536 Status
= EFI_SUCCESS
;
540 Status
= USBFloppyRead10 (UsbFloppyDevice
, Buffer
, LBA
, NumberOfBlocks
);
541 if (EFI_ERROR (Status
)) {
542 This
->Reset (This
, TRUE
);
543 Status
= EFI_DEVICE_ERROR
;
548 gBS
->RestoreTPL (OldTpl
);
555 USBFloppyWriteBlocks (
556 IN EFI_BLOCK_IO_PROTOCOL
*This
,
565 Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
568 This The EFI_BLOCK_IO_PROTOCOL instance.
569 MediaId The media id that the write request is for.
570 LBA The starting logical block address to be written.
571 The caller is responsible for writing to only
572 legitimate locations.
574 The size of the Buffer in bytes. This must be a multiple of
575 the intrinsic block size of the device.
576 Buffer A pointer to the source buffer for the data. The caller
577 is responsible for either having implicit or explicit ownership
581 EFI_INVALID_PARAMETER - Parameter is error
582 EFI_SUCCESS - Success
583 EFI_DEVICE_ERROR - Hardware Error
584 EFI_NO_MEDIA - No media
585 EFI_MEDIA_CHANGED - Media Change
586 EFI_BAD_BUFFER_SIZE - Buffer size is bad
590 USB_FLOPPY_DEV
*UsbFloppyDevice
;
592 EFI_BLOCK_IO_MEDIA
*Media
;
594 UINTN NumberOfBlocks
;
599 OldTpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
600 Status
= EFI_SUCCESS
;
604 UsbFloppyDevice
= USB_FLOPPY_DEV_FROM_THIS (This
);
610 Status
= EFI_INVALID_PARAMETER
;
614 if (BufferSize
== 0) {
615 Status
= EFI_SUCCESS
;
619 UsbFloppyTestUnitReady (UsbFloppyDevice
);
621 Status
= UsbFloppyDetectMedia (UsbFloppyDevice
, &MediaChange
);
622 if (EFI_ERROR (Status
)) {
624 Status
= EFI_DEVICE_ERROR
;
629 gBS
->RestoreTPL (OldTpl
);
630 gBS
->ReinstallProtocolInterface (
631 UsbFloppyDevice
->Handle
,
632 &gEfiBlockIoProtocolGuid
,
633 &UsbFloppyDevice
->BlkIo
,
634 &UsbFloppyDevice
->BlkIo
636 gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
639 Media
= UsbFloppyDevice
->BlkIo
.Media
;
640 BlockSize
= Media
->BlockSize
;
641 NumberOfBlocks
= BufferSize
/ BlockSize
;
643 if (!(Media
->MediaPresent
)) {
644 Status
= EFI_NO_MEDIA
;
648 if (MediaId
!= Media
->MediaId
) {
649 Status
= EFI_MEDIA_CHANGED
;
653 if (BufferSize
% BlockSize
!= 0) {
654 Status
= EFI_BAD_BUFFER_SIZE
;
658 if (LBA
> Media
->LastBlock
) {
659 Status
= EFI_INVALID_PARAMETER
;
663 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
664 Status
= EFI_INVALID_PARAMETER
;
668 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
669 Status
= EFI_INVALID_PARAMETER
;
673 if (UsbFloppyDevice
->BlkMedia
.ReadOnly
) {
674 Status
= EFI_WRITE_PROTECTED
;
678 if (!EFI_ERROR (Status
)) {
679 Status
= USBFloppyWrite10 (UsbFloppyDevice
, Buffer
, LBA
, 1);
680 if (EFI_ERROR (Status
)) {
681 This
->Reset (This
, TRUE
);
682 Status
= EFI_DEVICE_ERROR
;
688 Buffer
= (UINT8
*) Buffer
+ This
->Media
->BlockSize
;
690 if (NumberOfBlocks
== 0) {
691 Status
= EFI_SUCCESS
;
695 Status
= USBFloppyWrite10 (UsbFloppyDevice
, Buffer
, LBA
, NumberOfBlocks
);
696 if (EFI_ERROR (Status
)) {
697 This
->Reset (This
, TRUE
);
698 Status
= EFI_DEVICE_ERROR
;
703 gBS
->RestoreTPL (OldTpl
);
710 USBFloppyFlushBlocks (
711 IN EFI_BLOCK_IO_PROTOCOL
*This
716 Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
717 (In this driver, this function just returns EFI_SUCCESS.)
720 This The EFI_BLOCK_IO_PROTOCOL instance.
723 EFI_SUCCESS - Success