]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c
91a447de667c90b37c94ec7f6decfc5587a5a7c3
[mirror_edk2.git] / EdkModulePkg / Bus / Usb / UsbCbi / Dxe / Cbi0 / Cbi0.c
1 /*++
2
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
8
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.
11
12 Module Name:
13
14 Cbi0.c
15
16 Abstract:
17
18 --*/
19
20 #include "cbi.h"
21
22 extern EFI_COMPONENT_NAME_PROTOCOL gUsbCbi0ComponentName;
23 //
24 // Function prototypes
25 //
26 EFI_STATUS
27 EFIAPI
28 UsbCbi0DriverEntryPoint (
29 IN EFI_HANDLE ImageHandle,
30 IN EFI_SYSTEM_TABLE *SystemTable
31 );
32
33 //
34 // Bot Driver Binding Protocol
35 //
36 STATIC
37 EFI_STATUS
38 EFIAPI
39 Cbi0DriverBindingSupported (
40 IN EFI_DRIVER_BINDING_PROTOCOL *This,
41 IN EFI_HANDLE ControllerHandle,
42 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
43 );
44
45 STATIC
46 EFI_STATUS
47 EFIAPI
48 Cbi0DriverBindingStart (
49 IN EFI_DRIVER_BINDING_PROTOCOL *This,
50 IN EFI_HANDLE ControllerHandle,
51 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
52 );
53
54 STATIC
55 EFI_STATUS
56 EFIAPI
57 Cbi0DriverBindingStop (
58 IN EFI_DRIVER_BINDING_PROTOCOL *This,
59 IN EFI_HANDLE ControllerHandle,
60 IN UINTN NumberOfChildren,
61 IN EFI_HANDLE *ChildHandleBuffer
62 );
63
64 VOID
65 Cbi0ReportStatusCode (
66 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
67 IN EFI_STATUS_CODE_TYPE CodeType,
68 IN EFI_STATUS_CODE_VALUE Value
69 );
70
71
72 EFI_DRIVER_BINDING_PROTOCOL gUsbCbi0DriverBinding = {
73 Cbi0DriverBindingSupported,
74 Cbi0DriverBindingStart,
75 Cbi0DriverBindingStop,
76 0xa,
77 NULL,
78 NULL
79 };
80
81 STATIC
82 EFI_STATUS
83 Cbi0RecoveryReset (
84 IN USB_CBI_DEVICE *UsbCbiDev
85 );
86
87 STATIC
88 EFI_STATUS
89 Cbi0CommandPhase (
90 IN USB_CBI_DEVICE *UsbCbiDev,
91 IN VOID *Command,
92 IN UINT8 CommandSize,
93 IN UINT16 Timeout
94 );
95
96 STATIC
97 EFI_STATUS
98 Cbi0DataPhase (
99 IN USB_CBI_DEVICE *UsbCbiDev,
100 IN UINT32 *DataSize,
101 IN OUT VOID *DataBuffer,
102 IN EFI_USB_DATA_DIRECTION Direction,
103 IN UINT16 Timeout
104 );
105
106 STATIC
107 EFI_STATUS
108 Cbi0StatusPhase (
109 IN USB_CBI_DEVICE *UsbCbiDev,
110 OUT INTERRUPT_DATA_BLOCK *InterruptDataBlock,
111 IN UINT16 Timeout
112 );
113
114 //
115 // USB Atapi protocol prototype
116 //
117 STATIC
118 EFI_STATUS
119 EFIAPI
120 Cbi0AtapiCommand (
121 IN EFI_USB_ATAPI_PROTOCOL *This,
122 IN VOID *Command,
123 IN UINT8 CommandSize,
124 IN VOID *DataBuffer,
125 IN UINT32 BufferLength,
126 IN EFI_USB_DATA_DIRECTION Direction,
127 IN UINT16 TimeOutInMilliSeconds
128 );
129
130 STATIC
131 EFI_STATUS
132 EFIAPI
133 Cbi0MassStorageReset (
134 IN EFI_USB_ATAPI_PROTOCOL *This,
135 IN BOOLEAN ExtendedVerification
136 );
137
138 STATIC EFI_USB_ATAPI_PROTOCOL Cbi0AtapiProtocol = {
139 Cbi0AtapiCommand,
140 Cbi0MassStorageReset,
141 0
142 };
143
144 STATIC
145 EFI_STATUS
146 EFIAPI
147 Cbi0DriverBindingSupported (
148 IN EFI_DRIVER_BINDING_PROTOCOL *This,
149 IN EFI_HANDLE ControllerHandle,
150 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
151 )
152 /*++
153
154 Routine Description:
155 Test to see if this driver supports ControllerHandle. Any ControllerHandle
156 than contains a BlockIo and DiskIo protocol can be supported.
157
158 Arguments:
159 This - Protocol instance pointer.
160 ControllerHandle - Handle of device to test
161 RemainingDevicePath - Not used
162
163 Returns:
164 EFI_SUCCESS - This driver supports this device
165 EFI_ALREADY_STARTED - This driver is already running on this device
166 other - This driver does not support this device
167
168 --*/
169 {
170 EFI_STATUS Status;
171 EFI_USB_IO_PROTOCOL *UsbIo;
172 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
173
174 //
175 // Check if the Controller supports USB IO protocol
176 //
177 Status = gBS->OpenProtocol (
178 ControllerHandle,
179 &gEfiUsbIoProtocolGuid,
180 (VOID **) &UsbIo,
181 This->DriverBindingHandle,
182 ControllerHandle,
183 EFI_OPEN_PROTOCOL_BY_DRIVER
184 );
185 if (EFI_ERROR (Status)) {
186 return Status;
187 }
188 //
189 // Get the Default interface descriptor, now we only
190 // suppose interface 1
191 //
192 Status = UsbIo->UsbGetInterfaceDescriptor (
193 UsbIo,
194 &InterfaceDescriptor
195 );
196 if (EFI_ERROR (Status)) {
197 gBS->CloseProtocol (
198 ControllerHandle,
199 &gEfiUsbIoProtocolGuid,
200 This->DriverBindingHandle,
201 ControllerHandle
202 );
203 return Status;
204 }
205 //
206 // Check if it is a Cbi0 Type Mass Storage Device
207 //
208 if((InterfaceDescriptor.InterfaceClass != MASS_STORAGE_CLASS) ||
209 (InterfaceDescriptor.InterfaceProtocol != CBI0_INTERFACE_PROTOCOL)) {
210 Status = EFI_UNSUPPORTED;
211 } else {
212 Status = EFI_SUCCESS;
213 }
214
215 gBS->CloseProtocol (
216 ControllerHandle,
217 &gEfiUsbIoProtocolGuid,
218 This->DriverBindingHandle,
219 ControllerHandle
220 );
221
222 return Status;
223 }
224
225 STATIC
226 EFI_STATUS
227 EFIAPI
228 Cbi0DriverBindingStart (
229 IN EFI_DRIVER_BINDING_PROTOCOL *This,
230 IN EFI_HANDLE ControllerHandle,
231 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
232 )
233 /*++
234
235 Routine Description:
236 Start this driver on ControllerHandle by opening a Block IO and Disk IO
237 protocol, reading Device Path, and creating a child handle with a
238 Disk IO and device path protocol.
239
240 Arguments:
241 This - Protocol instance pointer.
242 ControllerHandle - Handle of device to bind driver to
243 RemainingDevicePath - Not used
244
245 Returns:
246 EFI_SUCCESS - This driver is added to DeviceHandle
247 EFI_ALREADY_STARTED - This driver is already running on DeviceHandle
248 other - This driver does not support this device
249 EFI_OUT_OF_RESOURCES- Can't allocate memory
250 EFI_UNSUPPORTED - Endpoint is not as expected
251 --*/
252 {
253 USB_CBI_DEVICE *UsbCbiDev;
254 UINT8 Index;
255 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
256 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
257 EFI_STATUS Status;
258 EFI_USB_IO_PROTOCOL *UsbIo;
259 UINT8 EndpointExistMask;
260
261 //
262 // Check if the Controller supports USB IO protocol
263 //
264 UsbCbiDev = NULL;
265
266 Status = gBS->OpenProtocol (
267 ControllerHandle,
268 &gEfiUsbIoProtocolGuid,
269 (VOID **) &UsbIo,
270 This->DriverBindingHandle,
271 ControllerHandle,
272 EFI_OPEN_PROTOCOL_BY_DRIVER
273 );
274 if (EFI_ERROR (Status)) {
275 return Status;
276 }
277 //
278 // Get the controller interface descriptor
279 //
280 Status = UsbIo->UsbGetInterfaceDescriptor (
281 UsbIo,
282 &InterfaceDescriptor
283 );
284 if (EFI_ERROR (Status)) {
285 gBS->CloseProtocol (
286 ControllerHandle,
287 &gEfiUsbIoProtocolGuid,
288 This->DriverBindingHandle,
289 ControllerHandle
290 );
291 return Status;
292 }
293
294 Cbi0AtapiProtocol.CommandProtocol = InterfaceDescriptor.InterfaceSubClass;
295
296 UsbCbiDev = AllocateZeroPool (sizeof (USB_CBI_DEVICE));
297 if (UsbCbiDev == NULL) {
298 gBS->CloseProtocol (
299 ControllerHandle,
300 &gEfiUsbIoProtocolGuid,
301 This->DriverBindingHandle,
302 ControllerHandle
303 );
304 return EFI_OUT_OF_RESOURCES;
305 }
306
307 UsbCbiDev->Signature = USB_CBI_DEVICE_SIGNATURE;
308 UsbCbiDev->UsbIo = UsbIo;
309 CopyMem (&UsbCbiDev->InterfaceDescriptor, &InterfaceDescriptor, sizeof (InterfaceDescriptor));
310 CopyMem (&UsbCbiDev->UsbAtapiProtocol, &Cbi0AtapiProtocol, sizeof (Cbi0AtapiProtocol));
311
312 //
313 // Get the Device Path Protocol on Controller's handle
314 //
315 Status = gBS->OpenProtocol (
316 ControllerHandle,
317 &gEfiDevicePathProtocolGuid,
318 (VOID **) &UsbCbiDev->DevicePath,
319 This->DriverBindingHandle,
320 ControllerHandle,
321 EFI_OPEN_PROTOCOL_GET_PROTOCOL
322 );
323
324 if (EFI_ERROR (Status)) {
325 gBS->CloseProtocol (
326 ControllerHandle,
327 &gEfiUsbIoProtocolGuid,
328 This->DriverBindingHandle,
329 ControllerHandle
330 );
331 if (UsbCbiDev != NULL) {
332 gBS->FreePool (UsbCbiDev);
333 }
334
335 return Status;
336 }
337 //
338 // Mask used to see whether all three kinds of endpoints exist,
339 // Mask value:
340 // bit0: bulk in endpoint;
341 // bit1: bulk out endpoint;
342 // bit2: interrupt in endpoint;
343 //
344 EndpointExistMask = 0;
345 for (Index = 0; Index < InterfaceDescriptor.NumEndpoints; Index++) {
346 UsbIo->UsbGetEndpointDescriptor (
347 UsbIo,
348 Index,
349 &EndpointDescriptor
350 );
351
352 //
353 // We parse bulk endpoint
354 //
355 if (EndpointDescriptor.Attributes == 0x02) {
356 if (EndpointDescriptor.EndpointAddress & 0x80) {
357 CopyMem (&UsbCbiDev->BulkInEndpointDescriptor, &EndpointDescriptor, sizeof (EndpointDescriptor));
358 EndpointExistMask |= bit (0);
359 } else {
360 CopyMem (&UsbCbiDev->BulkOutEndpointDescriptor, &EndpointDescriptor, sizeof (EndpointDescriptor));
361 EndpointExistMask |= bit (1);
362 }
363 }
364 //
365 // We parse interrupt endpoint
366 //
367 if (EndpointDescriptor.Attributes == 0x03) {
368 CopyMem (&UsbCbiDev->InterruptEndpointDescriptor, &EndpointDescriptor, sizeof (EndpointDescriptor));
369 EndpointExistMask |= bit (2);
370 }
371
372 }
373 //
374 // Double check we have all endpoints needed
375 //
376 if (EndpointExistMask != (bit (0) | bit (1) | bit (2))) {
377 gBS->CloseProtocol (
378 ControllerHandle,
379 &gEfiUsbIoProtocolGuid,
380 This->DriverBindingHandle,
381 ControllerHandle
382 );
383 if (UsbCbiDev != NULL) {
384 gBS->FreePool (UsbCbiDev);
385 }
386
387 return EFI_UNSUPPORTED;
388 }
389 //
390 // After installing Usb-Atapi protocol onto this handle
391 // it will be called by upper layer drivers such as Fat
392 //
393 Cbi0ReportStatusCode (
394 UsbCbiDev->DevicePath,
395 EFI_PROGRESS_CODE,
396 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE)
397 );
398
399 Status = gBS->InstallProtocolInterface (
400 &ControllerHandle,
401 &gEfiUsbAtapiProtocolGuid,
402 EFI_NATIVE_INTERFACE,
403 &UsbCbiDev->UsbAtapiProtocol
404 );
405 if (EFI_ERROR (Status)) {
406 gBS->CloseProtocol (
407 ControllerHandle,
408 &gEfiUsbIoProtocolGuid,
409 This->DriverBindingHandle,
410 ControllerHandle
411 );
412 if (UsbCbiDev != NULL) {
413 gBS->FreePool (UsbCbiDev);
414 }
415
416 return Status;
417 }
418
419 UsbCbiDev->ControllerNameTable = NULL;
420 AddUnicodeString (
421 "eng",
422 gUsbCbi0ComponentName.SupportedLanguages,
423 &UsbCbiDev->ControllerNameTable,
424 (CHAR16 *) L"Usb Cbi0 Mass Storage"
425 );
426
427 return EFI_SUCCESS;
428 }
429
430 STATIC
431 EFI_STATUS
432 EFIAPI
433 Cbi0DriverBindingStop (
434 IN EFI_DRIVER_BINDING_PROTOCOL *This,
435 IN EFI_HANDLE ControllerHandle,
436 IN UINTN NumberOfChildren,
437 IN EFI_HANDLE *ChildHandleBuffer
438 )
439 /*++
440
441 Routine Description:
442 Stop this driver on ControllerHandle. Support stoping any child handles
443 created by this driver.
444
445 Arguments:
446 This - Protocol instance pointer.
447 ControllerHandle - Handle of device to stop driver on
448 NumberOfChildren - Number of Children in the ChildHandleBuffer
449 ChildHandleBuffer - List of handles for the children we need to stop.
450
451 Returns:
452 EFI_SUCCESS - This driver is removed DeviceHandle
453 EFI_UNSUPPORTED - This driver was not removed from this device
454
455 --*/
456 {
457 EFI_STATUS Status;
458 EFI_USB_ATAPI_PROTOCOL *Cbi0AtapiProtocol;
459 USB_CBI_DEVICE *UsbCbiDev;
460
461 //
462 // Get our context back.
463 //
464 Status = gBS->OpenProtocol (
465 ControllerHandle,
466 &gEfiUsbAtapiProtocolGuid,
467 (VOID **) &Cbi0AtapiProtocol,
468 This->DriverBindingHandle,
469 ControllerHandle,
470 EFI_OPEN_PROTOCOL_GET_PROTOCOL
471 );
472 if (EFI_ERROR (Status)) {
473 return EFI_UNSUPPORTED;
474 }
475
476 UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (Cbi0AtapiProtocol);
477
478 Cbi0ReportStatusCode (
479 UsbCbiDev->DevicePath,
480 EFI_PROGRESS_CODE,
481 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE)
482 );
483
484 //
485 // Uninstall protocol
486 //
487 Status = gBS->UninstallProtocolInterface (
488 ControllerHandle,
489 &gEfiUsbAtapiProtocolGuid,
490 &UsbCbiDev->UsbAtapiProtocol
491 );
492 if (EFI_ERROR (Status)) {
493 return Status;
494 }
495
496 Status = gBS->CloseProtocol (
497 ControllerHandle,
498 &gEfiUsbIoProtocolGuid,
499 This->DriverBindingHandle,
500 ControllerHandle
501 );
502 //
503 // Free all allocated resources
504 //
505 if (UsbCbiDev->ControllerNameTable) {
506 FreeUnicodeStringTable (UsbCbiDev->ControllerNameTable);
507 }
508
509 gBS->FreePool (UsbCbiDev);
510
511 return Status;
512 }
513
514
515 STATIC
516 EFI_STATUS
517 Cbi0RecoveryReset (
518 IN USB_CBI_DEVICE *UsbCbiDev
519 )
520 /*++
521
522 Routine Description:
523
524 Cbi0 Recovery Reset routine
525
526 Arguments:
527
528 UsbCbiDev - Cbi0RecoveryReset
529
530 Returns:
531
532 EFI_SUCCESS - Success
533
534 --*/
535 {
536 UINT8 ResetCommand[12];
537 EFI_STATUS Status;
538 EFI_USB_IO_PROTOCOL *UsbIo;
539 UINT8 EndpointAddress;
540 UINT32 Result;
541 UINT16 Timeout;
542
543 UsbIo = UsbCbiDev->UsbIo;
544
545 Cbi0ReportStatusCode (
546 UsbCbiDev->DevicePath,
547 EFI_PROGRESS_CODE,
548 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET)
549 );
550 //
551 // CBI reset command protocol
552 //
553 SetMem (ResetCommand, sizeof (ResetCommand), 0xff);
554 ResetCommand[0] = 0x1d;
555 ResetCommand[1] = 0x04;
556
557 //
558 // (in millisecond unit)
559 //
560 Timeout = STALL_1_SECOND;
561
562 Status = Cbi0AtapiCommand (
563 &UsbCbiDev->UsbAtapiProtocol,
564 ResetCommand,
565 12,
566 NULL,
567 0,
568 EfiUsbNoData,
569 Timeout
570 );
571 if (EFI_ERROR (Status)) {
572 return Status;
573 }
574
575 gBS->Stall (100 * 1000);
576 //
577 // clear bulk in endpoint stall feature
578 //
579 EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress;
580 Status = UsbClearEndpointHalt (
581 UsbIo,
582 EndpointAddress,
583 &Result
584 );
585 if (EFI_ERROR (Status)) {
586 return Status;
587 }
588 //
589 // clear bulk out endpoint stall feature
590 //
591 EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress;
592 Status = UsbClearEndpointHalt (
593 UsbIo,
594 EndpointAddress,
595 &Result
596 );
597 //
598 // according to CBI spec, no need to clear interrupt endpoint feature.
599 //
600 return Status;
601 }
602
603 STATIC
604 EFI_STATUS
605 Cbi0CommandPhase (
606 IN USB_CBI_DEVICE *UsbCbiDev,
607 IN VOID *Command,
608 IN UINT8 CommandSize,
609 IN UINT16 Timeout
610 )
611 /*++
612
613 Routine Description:
614 Send ATAPI command through CBI0 interface.
615
616 Arguments:
617 UsbCbiDev - USB_CBI_DEVICE
618 Command - Command to send
619 CommandSize - Command size
620 Timeout - Time out value in milliseconds
621 Returns:
622 EFI_SUCCESS - Success
623 EFI_DEVICE_ERROR - Fail
624 Others
625
626 --*/
627 {
628 EFI_STATUS Status;
629 UINT32 Result;
630 EFI_USB_IO_PROTOCOL *UsbIo;
631 EFI_USB_DEVICE_REQUEST Request;
632
633 UsbIo = UsbCbiDev->UsbIo;
634
635 ZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST));
636
637 //
638 // Device request see CBI specification
639 //
640 Request.RequestType = 0x21;
641 Request.Request = 0x00;
642 Request.Value = 0;
643 Request.Index = 0;
644 Request.Length = CommandSize;
645
646 Status = UsbIo->UsbControlTransfer (
647 UsbIo,
648 &Request,
649 EfiUsbDataOut,
650 Timeout,
651 Command,
652 CommandSize,
653 &Result
654 );
655 if (EFI_ERROR (Status)) {
656 return EFI_DEVICE_ERROR;
657 }
658
659 return EFI_SUCCESS;
660 }
661
662 STATIC
663 EFI_STATUS
664 Cbi0DataPhase (
665 IN USB_CBI_DEVICE *UsbCbiDev,
666 IN UINT32 *DataSize,
667 IN OUT VOID *DataBuffer,
668 IN EFI_USB_DATA_DIRECTION Direction,
669 IN UINT16 Timeout
670 )
671 /*++
672
673 Routine Description:
674 Get/Send Data through CBI0 interface
675
676 Arguments:
677 UsbCbiDev - USB_CBI_DEVICE
678 DataSize - Data size
679 DataBuffer - Data buffer
680 Direction - IN/OUT/NODATA
681 Timeout - Time out value in milliseconds
682 Returns:
683 EFI_SUCCESS
684 Others
685
686 --*/
687 {
688 EFI_STATUS Status;
689 EFI_USB_IO_PROTOCOL *UsbIo;
690 UINT8 EndpointAddress;
691 UINTN Remain;
692 UINTN Increment;
693 UINT32 MaxPacketLength;
694 UINT8 *BufferPtr;
695 UINT32 Result;
696 UINTN TransferredSize;
697
698 UsbIo = UsbCbiDev->UsbIo;
699
700 Remain = *DataSize;
701 BufferPtr = (UINT8 *) DataBuffer;
702 TransferredSize = 0;
703 //
704 // retrieve the the max packet length of the given endpoint
705 //
706 if (Direction == EfiUsbDataIn) {
707 MaxPacketLength = UsbCbiDev->BulkInEndpointDescriptor.MaxPacketSize;
708 EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress;
709 } else {
710 MaxPacketLength = UsbCbiDev->BulkOutEndpointDescriptor.MaxPacketSize;
711 EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress;
712 }
713
714 while (Remain > 0) {
715
716 if (Remain > 16 * MaxPacketLength) {
717 Increment = 16 * MaxPacketLength;
718 } else {
719 Increment = Remain;
720 }
721
722 Status = UsbIo->UsbBulkTransfer (
723 UsbIo,
724 EndpointAddress,
725 BufferPtr,
726 &Increment,
727 Timeout,
728 &Result
729 );
730 TransferredSize += Increment;
731
732 if (EFI_ERROR (Status)) {
733 goto ErrorExit;
734 }
735
736 BufferPtr += Increment;
737 Remain -= Increment;
738 }
739
740 return EFI_SUCCESS;
741
742 ErrorExit:
743
744 if (Direction == EfiUsbDataIn) {
745 Cbi0ReportStatusCode (
746 UsbCbiDev->DevicePath,
747 EFI_ERROR_CODE | EFI_ERROR_MINOR,
748 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_INPUT_ERROR)
749 );
750 } else {
751 Cbi0ReportStatusCode (
752 UsbCbiDev->DevicePath,
753 EFI_ERROR_CODE | EFI_ERROR_MINOR,
754 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_OUTPUT_ERROR)
755 );
756 }
757
758 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
759 Status = Cbi0RecoveryReset (UsbCbiDev);
760 }
761
762 *DataSize = (UINT32) TransferredSize;
763 return Status;
764 }
765
766 STATIC
767 EFI_STATUS
768 Cbi0StatusPhase (
769 IN USB_CBI_DEVICE *UsbCbiDev,
770 OUT INTERRUPT_DATA_BLOCK *InterruptDataBlock,
771 IN UINT16 Timeout
772 )
773 /*++
774
775 Routine Description:
776 Get transfer status through BOT interface
777
778 Arguments:
779 UsbCbiDev - USB_CBI_DEVICE
780 InterruptDataBlock - Interrupt Data Block for interrupt transfer
781 Timeout - Time out value in milliseconds
782 Returns:
783 EFI_SUCCESS
784 Others
785
786 --*/
787 {
788 UINT8 EndpointAddress;
789 UINTN InterruptDataBlockLength;
790 UINT32 Result;
791 EFI_STATUS Status;
792
793 ZeroMem (InterruptDataBlock, sizeof (INTERRUPT_DATA_BLOCK));
794
795 EndpointAddress = UsbCbiDev->InterruptEndpointDescriptor.EndpointAddress;
796 InterruptDataBlockLength = sizeof (INTERRUPT_DATA_BLOCK);
797
798 Status = UsbCbiDev->UsbIo->UsbSyncInterruptTransfer (
799 UsbCbiDev->UsbIo,
800 EndpointAddress,
801 InterruptDataBlock,
802 &InterruptDataBlockLength,
803 Timeout,
804 &Result
805 );
806 if (EFI_ERROR (Status)) {
807 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
808 //
809 // just endpoint stall happens
810 //
811 UsbClearEndpointHalt (
812 UsbCbiDev->UsbIo,
813 EndpointAddress,
814 &Result
815 );
816 gBS->Stall (100 * 1000);
817 }
818
819 return Status;
820 }
821
822 return EFI_SUCCESS;
823 }
824 //
825 // Cbi0 Atapi Protocol Implementation
826 //
827 STATIC
828 EFI_STATUS
829 EFIAPI
830 Cbi0MassStorageReset (
831 IN EFI_USB_ATAPI_PROTOCOL *This,
832 IN BOOLEAN ExtendedVerification
833 )
834 /*++
835
836 Routine Description:
837 Reset CBI Devices
838
839 Arguments:
840 This - Protocol instance pointer.
841 ExtendedVerification - TRUE if we need to do strictly reset.
842
843 Returns:
844 EFI_SUCCESS - Command succeeded.
845 EFI_DEVICE_ERROR - Command failed.
846
847 --*/
848 {
849 EFI_STATUS Status;
850 USB_CBI_DEVICE *UsbCbiDev;
851
852 UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This);
853
854 if (ExtendedVerification) {
855 //
856 // UsbIo->UsbPortReset (UsbIo);
857 //
858 }
859
860 Status = Cbi0RecoveryReset (UsbCbiDev);
861 return Status;
862 }
863
864 STATIC
865 EFI_STATUS
866 EFIAPI
867 Cbi0AtapiCommand (
868 IN EFI_USB_ATAPI_PROTOCOL *This,
869 IN VOID *Command,
870 IN UINT8 CommandSize,
871 IN VOID *DataBuffer,
872 IN UINT32 BufferLength,
873 IN EFI_USB_DATA_DIRECTION Direction,
874 IN UINT16 TimeOutInMilliSeconds
875 )
876 /*++
877
878 Routine Description:
879 Send ATAPI command using BOT protocol.
880
881 Arguments:
882 This - Protocol instance pointer.
883 Command - Command buffer
884 CommandSize - Size of Command Buffer
885 DataBuffer - Data buffer
886 BufferLength - Length of Data buffer
887 Direction - Data direction of this command
888 TimeOutInMilliSeconds - Timeout value in ms
889
890 Returns:
891 EFI_SUCCESS - Command succeeded.
892 EFI_DEVICE_ERROR - Command failed.
893 EFI_INVALID_PARAMETER - Invalidate parameter
894 --*/
895 {
896 EFI_STATUS Status;
897 USB_CBI_DEVICE *UsbCbiDev;
898 UINT32 BufferSize;
899 INTERRUPT_DATA_BLOCK InterruptDataBlock;
900 EFI_STATUS DataPhaseStatus;
901
902 if (Direction != EfiUsbNoData) {
903 if (DataBuffer == NULL || BufferLength == 0) {
904 return EFI_INVALID_PARAMETER;
905 }
906 }
907
908 DataPhaseStatus = EFI_SUCCESS;
909 //
910 // Get the context
911 //
912 UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This);
913
914 //
915 // First send ATAPI command through Cbi
916 //
917 Status = Cbi0CommandPhase (
918 UsbCbiDev,
919 Command,
920 CommandSize,
921 TimeOutInMilliSeconds
922 );
923 if (EFI_ERROR (Status)) {
924 return EFI_DEVICE_ERROR;
925 }
926 //
927 // Send/Get Data if there is a Data Stage
928 //
929 switch (Direction) {
930
931 case EfiUsbDataIn:
932 case EfiUsbDataOut:
933 BufferSize = BufferLength;
934
935 DataPhaseStatus = Cbi0DataPhase (
936 UsbCbiDev,
937 &BufferSize,
938 DataBuffer,
939 Direction,
940 TimeOutInMilliSeconds
941 );
942 break;
943
944 case EfiUsbNoData:
945 break;
946 }
947
948 if (EFI_ERROR (DataPhaseStatus)) {
949 return EFI_DEVICE_ERROR;
950 }
951
952 //
953 // Status Phase
954 //
955 Status = Cbi0StatusPhase (
956 UsbCbiDev,
957 &InterruptDataBlock,
958 TimeOutInMilliSeconds
959 );
960 if (EFI_ERROR (Status)) {
961 return EFI_DEVICE_ERROR;
962 }
963
964 if (This->CommandProtocol != EFI_USB_SUBCLASS_UFI) {
965
966 if (InterruptDataBlock.bType == 0) {
967 //
968 // indicates command completion
969 //
970 switch (InterruptDataBlock.bValue & 0x03) {
971
972 case 0:
973 Status = EFI_SUCCESS;
974 break;
975
976 case 1:
977 Status = EFI_DEVICE_ERROR;
978 break;
979
980 case 2:
981 Status = Cbi0RecoveryReset (UsbCbiDev);
982 if (EFI_ERROR (Status)) {
983 UsbCbiDev->UsbIo->UsbPortReset (UsbCbiDev->UsbIo);
984 }
985
986 Status = EFI_DEVICE_ERROR;
987 break;
988
989 case 3:
990 Status = EFI_DEVICE_ERROR;
991 }
992 } else {
993 Status = DataPhaseStatus;
994 }
995
996 } else {
997 //
998 // UFI device, InterruptDataBlock.bType: ASC (Additional Sense Code)
999 // InterruptDataBlock.bValue: ASCQ (Additional Snese Code Qualifier)
1000 //
1001 Status = DataPhaseStatus;
1002 }
1003
1004 return Status;
1005 }
1006
1007 VOID
1008 Cbi0ReportStatusCode (
1009 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1010 IN EFI_STATUS_CODE_TYPE CodeType,
1011 IN EFI_STATUS_CODE_VALUE Value
1012 )
1013 /*++
1014
1015 Routine Description:
1016 Report Status Code in Usb Cbi0 Driver
1017
1018 Arguments:
1019 DevicePath - Use this to get Device Path
1020 CodeType - Status Code Type
1021 CodeValue - Status Code Value
1022
1023 Returns:
1024 None
1025
1026 --*/
1027 {
1028
1029 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1030 CodeType,
1031 Value,
1032 DevicePath
1033 );
1034 }