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.
23 // Bot Driver Binding Protocol
28 Cbi0DriverBindingSupported (
29 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
30 IN EFI_HANDLE ControllerHandle
,
31 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
37 Cbi0DriverBindingStart (
38 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
39 IN EFI_HANDLE ControllerHandle
,
40 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
46 Cbi0DriverBindingStop (
47 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
48 IN EFI_HANDLE ControllerHandle
,
49 IN UINTN NumberOfChildren
,
50 IN EFI_HANDLE
*ChildHandleBuffer
55 Cbi0ReportStatusCode (
56 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
57 IN EFI_STATUS_CODE_TYPE CodeType
,
58 IN EFI_STATUS_CODE_VALUE Value
62 EFI_DRIVER_BINDING_PROTOCOL gUsbCbi0DriverBinding
= {
63 Cbi0DriverBindingSupported
,
64 Cbi0DriverBindingStart
,
65 Cbi0DriverBindingStop
,
74 IN USB_CBI_DEVICE
*UsbCbiDev
80 IN USB_CBI_DEVICE
*UsbCbiDev
,
89 IN USB_CBI_DEVICE
*UsbCbiDev
,
91 IN OUT VOID
*DataBuffer
,
92 IN EFI_USB_DATA_DIRECTION Direction
,
99 IN USB_CBI_DEVICE
*UsbCbiDev
,
100 OUT INTERRUPT_DATA_BLOCK
*InterruptDataBlock
,
105 // USB Atapi protocol prototype
111 IN EFI_USB_ATAPI_PROTOCOL
*This
,
113 IN UINT8 CommandSize
,
115 IN UINT32 BufferLength
,
116 IN EFI_USB_DATA_DIRECTION Direction
,
117 IN UINT16 TimeOutInMilliSeconds
123 Cbi0MassStorageReset (
124 IN EFI_USB_ATAPI_PROTOCOL
*This
,
125 IN BOOLEAN ExtendedVerification
128 STATIC EFI_USB_ATAPI_PROTOCOL Cbi0AtapiProtocol
= {
130 Cbi0MassStorageReset
,
137 Cbi0DriverBindingSupported (
138 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
139 IN EFI_HANDLE ControllerHandle
,
140 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
145 Test to see if this driver supports ControllerHandle. Any ControllerHandle
146 than contains a BlockIo and DiskIo protocol can be supported.
149 This - Protocol instance pointer.
150 ControllerHandle - Handle of device to test
151 RemainingDevicePath - Not used
154 EFI_SUCCESS - This driver supports this device
155 EFI_ALREADY_STARTED - This driver is already running on this device
156 other - This driver does not support this device
161 EFI_USB_IO_PROTOCOL
*UsbIo
;
162 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
165 // Check if the Controller supports USB IO protocol
167 Status
= gBS
->OpenProtocol (
169 &gEfiUsbIoProtocolGuid
,
171 This
->DriverBindingHandle
,
173 EFI_OPEN_PROTOCOL_BY_DRIVER
175 if (EFI_ERROR (Status
)) {
179 // Get the Default interface descriptor, now we only
180 // suppose interface 1
182 Status
= UsbIo
->UsbGetInterfaceDescriptor (
186 if (EFI_ERROR (Status
)) {
189 &gEfiUsbIoProtocolGuid
,
190 This
->DriverBindingHandle
,
196 // Check if it is a Cbi0 Type Mass Storage Device
198 if((InterfaceDescriptor
.InterfaceClass
!= MASS_STORAGE_CLASS
) ||
199 (InterfaceDescriptor
.InterfaceProtocol
!= CBI0_INTERFACE_PROTOCOL
)) {
200 Status
= EFI_UNSUPPORTED
;
202 Status
= EFI_SUCCESS
;
207 &gEfiUsbIoProtocolGuid
,
208 This
->DriverBindingHandle
,
218 Cbi0DriverBindingStart (
219 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
220 IN EFI_HANDLE ControllerHandle
,
221 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
226 Start this driver on ControllerHandle by opening a Block IO and Disk IO
227 protocol, reading Device Path, and creating a child handle with a
228 Disk IO and device path protocol.
231 This - Protocol instance pointer.
232 ControllerHandle - Handle of device to bind driver to
233 RemainingDevicePath - Not used
236 EFI_SUCCESS - This driver is added to DeviceHandle
237 EFI_ALREADY_STARTED - This driver is already running on DeviceHandle
238 other - This driver does not support this device
239 EFI_OUT_OF_RESOURCES- Can't allocate memory
240 EFI_UNSUPPORTED - Endpoint is not as expected
243 USB_CBI_DEVICE
*UsbCbiDev
;
245 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
246 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
248 EFI_USB_IO_PROTOCOL
*UsbIo
;
249 UINT8 EndpointExistMask
;
252 // Check if the Controller supports USB IO protocol
256 Status
= gBS
->OpenProtocol (
258 &gEfiUsbIoProtocolGuid
,
260 This
->DriverBindingHandle
,
262 EFI_OPEN_PROTOCOL_BY_DRIVER
264 if (EFI_ERROR (Status
)) {
268 // Get the controller interface descriptor
270 Status
= UsbIo
->UsbGetInterfaceDescriptor (
274 if (EFI_ERROR (Status
)) {
277 &gEfiUsbIoProtocolGuid
,
278 This
->DriverBindingHandle
,
284 Cbi0AtapiProtocol
.CommandProtocol
= InterfaceDescriptor
.InterfaceSubClass
;
286 UsbCbiDev
= AllocateZeroPool (sizeof (USB_CBI_DEVICE
));
287 if (UsbCbiDev
== NULL
) {
290 &gEfiUsbIoProtocolGuid
,
291 This
->DriverBindingHandle
,
294 return EFI_OUT_OF_RESOURCES
;
297 UsbCbiDev
->Signature
= USB_CBI_DEVICE_SIGNATURE
;
298 UsbCbiDev
->UsbIo
= UsbIo
;
299 CopyMem (&UsbCbiDev
->InterfaceDescriptor
, &InterfaceDescriptor
, sizeof (InterfaceDescriptor
));
300 CopyMem (&UsbCbiDev
->UsbAtapiProtocol
, &Cbi0AtapiProtocol
, sizeof (Cbi0AtapiProtocol
));
303 // Get the Device Path Protocol on Controller's handle
305 Status
= gBS
->OpenProtocol (
307 &gEfiDevicePathProtocolGuid
,
308 (VOID
**) &UsbCbiDev
->DevicePath
,
309 This
->DriverBindingHandle
,
311 EFI_OPEN_PROTOCOL_GET_PROTOCOL
314 if (EFI_ERROR (Status
)) {
317 &gEfiUsbIoProtocolGuid
,
318 This
->DriverBindingHandle
,
321 if (UsbCbiDev
!= NULL
) {
322 gBS
->FreePool (UsbCbiDev
);
328 // Mask used to see whether all three kinds of endpoints exist,
330 // bit0: bulk in endpoint;
331 // bit1: bulk out endpoint;
332 // bit2: interrupt in endpoint;
334 EndpointExistMask
= 0;
335 for (Index
= 0; Index
< InterfaceDescriptor
.NumEndpoints
; Index
++) {
336 UsbIo
->UsbGetEndpointDescriptor (
343 // We parse bulk endpoint
345 if (EndpointDescriptor
.Attributes
== 0x02) {
346 if (EndpointDescriptor
.EndpointAddress
& 0x80) {
347 CopyMem (&UsbCbiDev
->BulkInEndpointDescriptor
, &EndpointDescriptor
, sizeof (EndpointDescriptor
));
348 EndpointExistMask
|= bit (0);
350 CopyMem (&UsbCbiDev
->BulkOutEndpointDescriptor
, &EndpointDescriptor
, sizeof (EndpointDescriptor
));
351 EndpointExistMask
|= bit (1);
355 // We parse interrupt endpoint
357 if (EndpointDescriptor
.Attributes
== 0x03) {
358 CopyMem (&UsbCbiDev
->InterruptEndpointDescriptor
, &EndpointDescriptor
, sizeof (EndpointDescriptor
));
359 EndpointExistMask
|= bit (2);
364 // Double check we have all endpoints needed
366 if (EndpointExistMask
!= (bit (0) | bit (1) | bit (2))) {
369 &gEfiUsbIoProtocolGuid
,
370 This
->DriverBindingHandle
,
373 if (UsbCbiDev
!= NULL
) {
374 gBS
->FreePool (UsbCbiDev
);
377 return EFI_UNSUPPORTED
;
380 // After installing Usb-Atapi protocol onto this handle
381 // it will be called by upper layer drivers such as Fat
383 Cbi0ReportStatusCode (
384 UsbCbiDev
->DevicePath
,
386 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_ENABLE
)
389 Status
= gBS
->InstallProtocolInterface (
391 &gEfiUsbAtapiProtocolGuid
,
392 EFI_NATIVE_INTERFACE
,
393 &UsbCbiDev
->UsbAtapiProtocol
395 if (EFI_ERROR (Status
)) {
398 &gEfiUsbIoProtocolGuid
,
399 This
->DriverBindingHandle
,
402 if (UsbCbiDev
!= NULL
) {
403 gBS
->FreePool (UsbCbiDev
);
409 UsbCbiDev
->ControllerNameTable
= NULL
;
412 gUsbCbi0ComponentName
.SupportedLanguages
,
413 &UsbCbiDev
->ControllerNameTable
,
414 (CHAR16
*) L
"Usb Cbi0 Mass Storage"
423 Cbi0DriverBindingStop (
424 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
425 IN EFI_HANDLE ControllerHandle
,
426 IN UINTN NumberOfChildren
,
427 IN EFI_HANDLE
*ChildHandleBuffer
432 Stop this driver on ControllerHandle. Support stoping any child handles
433 created by this driver.
436 This - Protocol instance pointer.
437 ControllerHandle - Handle of device to stop driver on
438 NumberOfChildren - Number of Children in the ChildHandleBuffer
439 ChildHandleBuffer - List of handles for the children we need to stop.
442 EFI_SUCCESS - This driver is removed DeviceHandle
443 EFI_UNSUPPORTED - This driver was not removed from this device
448 EFI_USB_ATAPI_PROTOCOL
*Cbi0AtapiProtocol
;
449 USB_CBI_DEVICE
*UsbCbiDev
;
452 // Get our context back.
454 Status
= gBS
->OpenProtocol (
456 &gEfiUsbAtapiProtocolGuid
,
457 (VOID
**) &Cbi0AtapiProtocol
,
458 This
->DriverBindingHandle
,
460 EFI_OPEN_PROTOCOL_GET_PROTOCOL
462 if (EFI_ERROR (Status
)) {
463 return EFI_UNSUPPORTED
;
466 UsbCbiDev
= USB_CBI_DEVICE_FROM_THIS (Cbi0AtapiProtocol
);
468 Cbi0ReportStatusCode (
469 UsbCbiDev
->DevicePath
,
471 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_DISABLE
)
475 // Uninstall protocol
477 Status
= gBS
->UninstallProtocolInterface (
479 &gEfiUsbAtapiProtocolGuid
,
480 &UsbCbiDev
->UsbAtapiProtocol
482 if (EFI_ERROR (Status
)) {
486 Status
= gBS
->CloseProtocol (
488 &gEfiUsbIoProtocolGuid
,
489 This
->DriverBindingHandle
,
493 // Free all allocated resources
495 if (UsbCbiDev
->ControllerNameTable
) {
496 FreeUnicodeStringTable (UsbCbiDev
->ControllerNameTable
);
499 gBS
->FreePool (UsbCbiDev
);
508 IN USB_CBI_DEVICE
*UsbCbiDev
514 Cbi0 Recovery Reset routine
518 UsbCbiDev - Cbi0RecoveryReset
522 EFI_SUCCESS - Success
526 UINT8 ResetCommand
[12];
528 EFI_USB_IO_PROTOCOL
*UsbIo
;
529 UINT8 EndpointAddress
;
533 UsbIo
= UsbCbiDev
->UsbIo
;
535 Cbi0ReportStatusCode (
536 UsbCbiDev
->DevicePath
,
538 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_RESET
)
541 // CBI reset command protocol
543 SetMem (ResetCommand
, sizeof (ResetCommand
), 0xff);
544 ResetCommand
[0] = 0x1d;
545 ResetCommand
[1] = 0x04;
548 // (in millisecond unit)
550 Timeout
= STALL_1_SECOND
;
552 Status
= Cbi0AtapiCommand (
553 &UsbCbiDev
->UsbAtapiProtocol
,
561 if (EFI_ERROR (Status
)) {
565 gBS
->Stall (100 * 1000);
567 // clear bulk in endpoint stall feature
569 EndpointAddress
= UsbCbiDev
->BulkInEndpointDescriptor
.EndpointAddress
;
570 Status
= UsbClearEndpointHalt (
575 if (EFI_ERROR (Status
)) {
579 // clear bulk out endpoint stall feature
581 EndpointAddress
= UsbCbiDev
->BulkOutEndpointDescriptor
.EndpointAddress
;
582 Status
= UsbClearEndpointHalt (
588 // according to CBI spec, no need to clear interrupt endpoint feature.
596 IN USB_CBI_DEVICE
*UsbCbiDev
,
598 IN UINT8 CommandSize
,
604 Send ATAPI command through CBI0 interface.
607 UsbCbiDev - USB_CBI_DEVICE
608 Command - Command to send
609 CommandSize - Command size
610 Timeout - Time out value in milliseconds
612 EFI_SUCCESS - Success
613 EFI_DEVICE_ERROR - Fail
620 EFI_USB_IO_PROTOCOL
*UsbIo
;
621 EFI_USB_DEVICE_REQUEST Request
;
623 UsbIo
= UsbCbiDev
->UsbIo
;
625 ZeroMem (&Request
, sizeof (EFI_USB_DEVICE_REQUEST
));
628 // Device request see CBI specification
630 Request
.RequestType
= 0x21;
631 Request
.Request
= 0x00;
634 Request
.Length
= CommandSize
;
636 Status
= UsbIo
->UsbControlTransfer (
645 if (EFI_ERROR (Status
)) {
646 return EFI_DEVICE_ERROR
;
655 IN USB_CBI_DEVICE
*UsbCbiDev
,
657 IN OUT VOID
*DataBuffer
,
658 IN EFI_USB_DATA_DIRECTION Direction
,
664 Get/Send Data through CBI0 interface
667 UsbCbiDev - USB_CBI_DEVICE
669 DataBuffer - Data buffer
670 Direction - IN/OUT/NODATA
671 Timeout - Time out value in milliseconds
679 EFI_USB_IO_PROTOCOL
*UsbIo
;
680 UINT8 EndpointAddress
;
683 UINT32 MaxPacketLength
;
686 UINTN TransferredSize
;
688 UsbIo
= UsbCbiDev
->UsbIo
;
691 BufferPtr
= (UINT8
*) DataBuffer
;
694 // retrieve the the max packet length of the given endpoint
696 if (Direction
== EfiUsbDataIn
) {
697 MaxPacketLength
= UsbCbiDev
->BulkInEndpointDescriptor
.MaxPacketSize
;
698 EndpointAddress
= UsbCbiDev
->BulkInEndpointDescriptor
.EndpointAddress
;
700 MaxPacketLength
= UsbCbiDev
->BulkOutEndpointDescriptor
.MaxPacketSize
;
701 EndpointAddress
= UsbCbiDev
->BulkOutEndpointDescriptor
.EndpointAddress
;
706 if (Remain
> 16 * MaxPacketLength
) {
707 Increment
= 16 * MaxPacketLength
;
712 Status
= UsbIo
->UsbBulkTransfer (
720 TransferredSize
+= Increment
;
722 if (EFI_ERROR (Status
)) {
726 BufferPtr
+= Increment
;
734 if (Direction
== EfiUsbDataIn
) {
735 Cbi0ReportStatusCode (
736 UsbCbiDev
->DevicePath
,
737 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
738 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_EC_INPUT_ERROR
)
741 Cbi0ReportStatusCode (
742 UsbCbiDev
->DevicePath
,
743 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
744 (EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_EC_OUTPUT_ERROR
)
748 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
749 Status
= Cbi0RecoveryReset (UsbCbiDev
);
752 *DataSize
= (UINT32
) TransferredSize
;
759 IN USB_CBI_DEVICE
*UsbCbiDev
,
760 OUT INTERRUPT_DATA_BLOCK
*InterruptDataBlock
,
766 Get transfer status through BOT interface
769 UsbCbiDev - USB_CBI_DEVICE
770 InterruptDataBlock - Interrupt Data Block for interrupt transfer
771 Timeout - Time out value in milliseconds
778 UINT8 EndpointAddress
;
779 UINTN InterruptDataBlockLength
;
783 ZeroMem (InterruptDataBlock
, sizeof (INTERRUPT_DATA_BLOCK
));
785 EndpointAddress
= UsbCbiDev
->InterruptEndpointDescriptor
.EndpointAddress
;
786 InterruptDataBlockLength
= sizeof (INTERRUPT_DATA_BLOCK
);
788 Status
= UsbCbiDev
->UsbIo
->UsbSyncInterruptTransfer (
792 &InterruptDataBlockLength
,
796 if (EFI_ERROR (Status
)) {
797 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
799 // just endpoint stall happens
801 UsbClearEndpointHalt (
806 gBS
->Stall (100 * 1000);
815 // Cbi0 Atapi Protocol Implementation
820 Cbi0MassStorageReset (
821 IN EFI_USB_ATAPI_PROTOCOL
*This
,
822 IN BOOLEAN ExtendedVerification
830 This - Protocol instance pointer.
831 ExtendedVerification - TRUE if we need to do strictly reset.
834 EFI_SUCCESS - Command succeeded.
835 EFI_DEVICE_ERROR - Command failed.
840 USB_CBI_DEVICE
*UsbCbiDev
;
842 UsbCbiDev
= USB_CBI_DEVICE_FROM_THIS (This
);
844 if (ExtendedVerification
) {
846 // UsbIo->UsbPortReset (UsbIo);
850 Status
= Cbi0RecoveryReset (UsbCbiDev
);
858 IN EFI_USB_ATAPI_PROTOCOL
*This
,
860 IN UINT8 CommandSize
,
862 IN UINT32 BufferLength
,
863 IN EFI_USB_DATA_DIRECTION Direction
,
864 IN UINT16 TimeOutInMilliSeconds
869 Send ATAPI command using BOT protocol.
872 This - Protocol instance pointer.
873 Command - Command buffer
874 CommandSize - Size of Command Buffer
875 DataBuffer - Data buffer
876 BufferLength - Length of Data buffer
877 Direction - Data direction of this command
878 TimeOutInMilliSeconds - Timeout value in ms
881 EFI_SUCCESS - Command succeeded.
882 EFI_DEVICE_ERROR - Command failed.
883 EFI_INVALID_PARAMETER - Invalidate parameter
887 USB_CBI_DEVICE
*UsbCbiDev
;
889 INTERRUPT_DATA_BLOCK InterruptDataBlock
;
890 EFI_STATUS DataPhaseStatus
;
892 if (Direction
!= EfiUsbNoData
) {
893 if (DataBuffer
== NULL
|| BufferLength
== 0) {
894 return EFI_INVALID_PARAMETER
;
898 DataPhaseStatus
= EFI_SUCCESS
;
902 UsbCbiDev
= USB_CBI_DEVICE_FROM_THIS (This
);
905 // First send ATAPI command through Cbi
907 Status
= Cbi0CommandPhase (
911 TimeOutInMilliSeconds
913 if (EFI_ERROR (Status
)) {
914 return EFI_DEVICE_ERROR
;
917 // Send/Get Data if there is a Data Stage
923 BufferSize
= BufferLength
;
925 DataPhaseStatus
= Cbi0DataPhase (
930 TimeOutInMilliSeconds
938 if (EFI_ERROR (DataPhaseStatus
)) {
939 return EFI_DEVICE_ERROR
;
945 Status
= Cbi0StatusPhase (
948 TimeOutInMilliSeconds
950 if (EFI_ERROR (Status
)) {
951 return EFI_DEVICE_ERROR
;
954 if (This
->CommandProtocol
!= EFI_USB_SUBCLASS_UFI
) {
956 if (InterruptDataBlock
.bType
== 0) {
958 // indicates command completion
960 switch (InterruptDataBlock
.bValue
& 0x03) {
963 Status
= EFI_SUCCESS
;
967 Status
= EFI_DEVICE_ERROR
;
971 Status
= Cbi0RecoveryReset (UsbCbiDev
);
972 if (EFI_ERROR (Status
)) {
973 UsbCbiDev
->UsbIo
->UsbPortReset (UsbCbiDev
->UsbIo
);
976 Status
= EFI_DEVICE_ERROR
;
980 Status
= EFI_DEVICE_ERROR
;
983 Status
= DataPhaseStatus
;
988 // UFI device, InterruptDataBlock.bType: ASC (Additional Sense Code)
989 // InterruptDataBlock.bValue: ASCQ (Additional Snese Code Qualifier)
991 Status
= DataPhaseStatus
;
999 Cbi0ReportStatusCode (
1000 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1001 IN EFI_STATUS_CODE_TYPE CodeType
,
1002 IN EFI_STATUS_CODE_VALUE Value
1006 Routine Description:
1007 Report Status Code in Usb Cbi0 Driver
1010 DevicePath - Use this to get Device Path
1011 CodeType - Status Code Type
1012 CodeValue - Status Code Value
1020 REPORT_STATUS_CODE_WITH_DEVICE_PATH (