]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c
Fix component name bugs when input Controller Name is invalid
[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 EFI_USB_IO_PROTOCOL *UsbIo;
461
462 //
463 // Get our context back.
464 //
465 Status = gBS->OpenProtocol (
466 ControllerHandle,
467 &gEfiUsbAtapiProtocolGuid,
468 (VOID **) &Cbi0AtapiProtocol,
469 This->DriverBindingHandle,
470 ControllerHandle,
471 EFI_OPEN_PROTOCOL_GET_PROTOCOL
472 );
473 if (EFI_ERROR (Status)) {
474 return EFI_UNSUPPORTED;
475 }
476
477 UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (Cbi0AtapiProtocol);
478
479 UsbIo = UsbCbiDev->UsbIo;
480
481 Cbi0ReportStatusCode (
482 UsbCbiDev->DevicePath,
483 EFI_PROGRESS_CODE,
484 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE)
485 );
486
487 //
488 // Uninstall protocol
489 //
490 Status = gBS->UninstallProtocolInterface (
491 ControllerHandle,
492 &gEfiUsbAtapiProtocolGuid,
493 &UsbCbiDev->UsbAtapiProtocol
494 );
495 if (EFI_ERROR (Status)) {
496 return Status;
497 }
498
499 Status = gBS->CloseProtocol (
500 ControllerHandle,
501 &gEfiUsbIoProtocolGuid,
502 This->DriverBindingHandle,
503 ControllerHandle
504 );
505 //
506 // Free all allocated resources
507 //
508 if (UsbCbiDev->ControllerNameTable) {
509 FreeUnicodeStringTable (UsbCbiDev->ControllerNameTable);
510 }
511
512 gBS->FreePool (UsbCbiDev);
513
514 return Status;
515 }
516
517
518 STATIC
519 EFI_STATUS
520 Cbi0RecoveryReset (
521 IN USB_CBI_DEVICE *UsbCbiDev
522 )
523 /*++
524
525 Routine Description:
526
527 Cbi0 Recovery Reset routine
528
529 Arguments:
530
531 UsbCbiDev - Cbi0RecoveryReset
532
533 Returns:
534
535 EFI_SUCCESS - Success
536
537 --*/
538 {
539 UINT8 ResetCommand[12];
540 EFI_STATUS Status;
541 EFI_USB_IO_PROTOCOL *UsbIo;
542 UINT8 EndpointAddress;
543 UINT32 Result;
544 UINT16 Timeout;
545
546 UsbIo = UsbCbiDev->UsbIo;
547
548 Cbi0ReportStatusCode (
549 UsbCbiDev->DevicePath,
550 EFI_PROGRESS_CODE,
551 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET)
552 );
553 //
554 // CBI reset command protocol
555 //
556 SetMem (ResetCommand, sizeof (ResetCommand), 0xff);
557 ResetCommand[0] = 0x1d;
558 ResetCommand[1] = 0x04;
559
560 //
561 // (in millisecond unit)
562 //
563 Timeout = STALL_1_SECOND;
564
565 Status = Cbi0AtapiCommand (
566 &UsbCbiDev->UsbAtapiProtocol,
567 ResetCommand,
568 12,
569 NULL,
570 0,
571 EfiUsbNoData,
572 Timeout
573 );
574 if (EFI_ERROR (Status)) {
575 return Status;
576 }
577
578 gBS->Stall (100 * 1000);
579 //
580 // clear bulk in endpoint stall feature
581 //
582 EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress;
583 Status = UsbClearEndpointHalt (
584 UsbIo,
585 EndpointAddress,
586 &Result
587 );
588 if (EFI_ERROR (Status)) {
589 return Status;
590 }
591 //
592 // clear bulk out endpoint stall feature
593 //
594 EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress;
595 Status = UsbClearEndpointHalt (
596 UsbIo,
597 EndpointAddress,
598 &Result
599 );
600 //
601 // according to CBI spec, no need to clear interrupt endpoint feature.
602 //
603 return Status;
604 }
605
606 STATIC
607 EFI_STATUS
608 Cbi0CommandPhase (
609 IN USB_CBI_DEVICE *UsbCbiDev,
610 IN VOID *Command,
611 IN UINT8 CommandSize,
612 IN UINT16 Timeout
613 )
614 /*++
615
616 Routine Description:
617 Send ATAPI command through CBI0 interface.
618
619 Arguments:
620 UsbCbiDev - USB_CBI_DEVICE
621 Command - Command to send
622 CommandSize - Command size
623 Timeout - Time out value in milliseconds
624 Returns:
625 EFI_SUCCESS - Success
626 EFI_DEVICE_ERROR - Fail
627 Others
628
629 --*/
630 {
631 EFI_STATUS Status;
632 UINT32 Result;
633 EFI_USB_IO_PROTOCOL *UsbIo;
634 EFI_USB_DEVICE_REQUEST Request;
635
636 UsbIo = UsbCbiDev->UsbIo;
637
638 ZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST));
639
640 //
641 // Device request see CBI specification
642 //
643 Request.RequestType = 0x21;
644 Request.Request = 0x00;
645 Request.Value = 0;
646 Request.Index = 0;
647 Request.Length = CommandSize;
648
649 Status = UsbIo->UsbControlTransfer (
650 UsbIo,
651 &Request,
652 EfiUsbDataOut,
653 Timeout,
654 Command,
655 CommandSize,
656 &Result
657 );
658 if (EFI_ERROR (Status)) {
659 return EFI_DEVICE_ERROR;
660 }
661
662 return EFI_SUCCESS;
663 }
664
665 STATIC
666 EFI_STATUS
667 Cbi0DataPhase (
668 IN USB_CBI_DEVICE *UsbCbiDev,
669 IN UINT32 *DataSize,
670 IN OUT VOID *DataBuffer,
671 IN EFI_USB_DATA_DIRECTION Direction,
672 IN UINT16 Timeout
673 )
674 /*++
675
676 Routine Description:
677 Get/Send Data through CBI0 interface
678
679 Arguments:
680 UsbCbiDev - USB_CBI_DEVICE
681 DataSize - Data size
682 DataBuffer - Data buffer
683 Direction - IN/OUT/NODATA
684 Timeout - Time out value in milliseconds
685 Returns:
686 EFI_SUCCESS
687 Others
688
689 --*/
690 {
691 EFI_STATUS Status;
692 EFI_USB_IO_PROTOCOL *UsbIo;
693 UINT8 EndpointAddress;
694 UINTN Remain;
695 UINTN Increment;
696 UINT32 MaxPacketLength;
697 UINT8 *BufferPtr;
698 UINT32 Result;
699 UINTN TransferredSize;
700
701 UsbIo = UsbCbiDev->UsbIo;
702
703 Remain = *DataSize;
704 BufferPtr = (UINT8 *) DataBuffer;
705 TransferredSize = 0;
706 //
707 // retrieve the the max packet length of the given endpoint
708 //
709 if (Direction == EfiUsbDataIn) {
710 MaxPacketLength = UsbCbiDev->BulkInEndpointDescriptor.MaxPacketSize;
711 EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress;
712 } else {
713 MaxPacketLength = UsbCbiDev->BulkOutEndpointDescriptor.MaxPacketSize;
714 EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress;
715 }
716
717 while (Remain > 0) {
718
719 if (Remain > 16 * MaxPacketLength) {
720 Increment = 16 * MaxPacketLength;
721 } else {
722 Increment = Remain;
723 }
724
725 Status = UsbIo->UsbBulkTransfer (
726 UsbIo,
727 EndpointAddress,
728 BufferPtr,
729 &Increment,
730 Timeout,
731 &Result
732 );
733 TransferredSize += Increment;
734
735 if (EFI_ERROR (Status)) {
736 goto ErrorExit;
737 }
738
739 BufferPtr += Increment;
740 Remain -= Increment;
741 }
742
743 return EFI_SUCCESS;
744
745 ErrorExit:
746
747 if (Direction == EfiUsbDataIn) {
748 Cbi0ReportStatusCode (
749 UsbCbiDev->DevicePath,
750 EFI_ERROR_CODE | EFI_ERROR_MINOR,
751 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_INPUT_ERROR)
752 );
753 } else {
754 Cbi0ReportStatusCode (
755 UsbCbiDev->DevicePath,
756 EFI_ERROR_CODE | EFI_ERROR_MINOR,
757 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_OUTPUT_ERROR)
758 );
759 }
760
761 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
762 Status = Cbi0RecoveryReset (UsbCbiDev);
763 }
764
765 *DataSize = (UINT32) TransferredSize;
766 return Status;
767 }
768
769 STATIC
770 EFI_STATUS
771 Cbi0StatusPhase (
772 IN USB_CBI_DEVICE *UsbCbiDev,
773 OUT INTERRUPT_DATA_BLOCK *InterruptDataBlock,
774 IN UINT16 Timeout
775 )
776 /*++
777
778 Routine Description:
779 Get transfer status through BOT interface
780
781 Arguments:
782 UsbCbiDev - USB_CBI_DEVICE
783 InterruptDataBlock - Interrupt Data Block for interrupt transfer
784 Timeout - Time out value in milliseconds
785 Returns:
786 EFI_SUCCESS
787 Others
788
789 --*/
790 {
791 UINT8 EndpointAddress;
792 UINTN InterruptDataBlockLength;
793 UINT32 Result;
794 EFI_STATUS Status;
795
796 ZeroMem (InterruptDataBlock, sizeof (INTERRUPT_DATA_BLOCK));
797
798 EndpointAddress = UsbCbiDev->InterruptEndpointDescriptor.EndpointAddress;
799 InterruptDataBlockLength = sizeof (INTERRUPT_DATA_BLOCK);
800
801 Status = UsbCbiDev->UsbIo->UsbSyncInterruptTransfer (
802 UsbCbiDev->UsbIo,
803 EndpointAddress,
804 InterruptDataBlock,
805 &InterruptDataBlockLength,
806 Timeout,
807 &Result
808 );
809 if (EFI_ERROR (Status)) {
810 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
811 //
812 // just endpoint stall happens
813 //
814 UsbClearEndpointHalt (
815 UsbCbiDev->UsbIo,
816 EndpointAddress,
817 &Result
818 );
819 gBS->Stall (100 * 1000);
820 }
821
822 return Status;
823 }
824
825 return EFI_SUCCESS;
826 }
827 //
828 // Cbi0 Atapi Protocol Implementation
829 //
830 STATIC
831 EFI_STATUS
832 EFIAPI
833 Cbi0MassStorageReset (
834 IN EFI_USB_ATAPI_PROTOCOL *This,
835 IN BOOLEAN ExtendedVerification
836 )
837 /*++
838
839 Routine Description:
840 Reset CBI Devices
841
842 Arguments:
843 This - Protocol instance pointer.
844 ExtendedVerification - TRUE if we need to do strictly reset.
845
846 Returns:
847 EFI_SUCCESS - Command succeeded.
848 EFI_DEVICE_ERROR - Command failed.
849
850 --*/
851 {
852 EFI_STATUS Status;
853 EFI_USB_IO_PROTOCOL *UsbIo;
854 USB_CBI_DEVICE *UsbCbiDev;
855
856 UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This);
857 UsbIo = UsbCbiDev->UsbIo;
858
859 if (ExtendedVerification) {
860 //
861 // UsbIo->UsbPortReset (UsbIo);
862 //
863 }
864
865 Status = Cbi0RecoveryReset (UsbCbiDev);
866 return Status;
867 }
868
869 STATIC
870 EFI_STATUS
871 EFIAPI
872 Cbi0AtapiCommand (
873 IN EFI_USB_ATAPI_PROTOCOL *This,
874 IN VOID *Command,
875 IN UINT8 CommandSize,
876 IN VOID *DataBuffer,
877 IN UINT32 BufferLength,
878 IN EFI_USB_DATA_DIRECTION Direction,
879 IN UINT16 TimeOutInMilliSeconds
880 )
881 /*++
882
883 Routine Description:
884 Send ATAPI command using BOT protocol.
885
886 Arguments:
887 This - Protocol instance pointer.
888 Command - Command buffer
889 CommandSize - Size of Command Buffer
890 DataBuffer - Data buffer
891 BufferLength - Length of Data buffer
892 Direction - Data direction of this command
893 TimeOutInMilliSeconds - Timeout value in ms
894
895 Returns:
896 EFI_SUCCESS - Command succeeded.
897 EFI_DEVICE_ERROR - Command failed.
898 EFI_INVALID_PARAMETER - Invalidate parameter
899 --*/
900 {
901 EFI_STATUS Status;
902 USB_CBI_DEVICE *UsbCbiDev;
903 UINT32 BufferSize;
904 INTERRUPT_DATA_BLOCK InterruptDataBlock;
905 EFI_STATUS DataPhaseStatus;
906
907 if (Direction != EfiUsbNoData) {
908 if (DataBuffer == NULL || BufferLength == 0) {
909 return EFI_INVALID_PARAMETER;
910 }
911 }
912
913 DataPhaseStatus = EFI_SUCCESS;
914 //
915 // Get the context
916 //
917 UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This);
918
919 //
920 // First send ATAPI command through Cbi
921 //
922 Status = Cbi0CommandPhase (
923 UsbCbiDev,
924 Command,
925 CommandSize,
926 TimeOutInMilliSeconds
927 );
928 if (EFI_ERROR (Status)) {
929 return EFI_DEVICE_ERROR;
930 }
931 //
932 // Send/Get Data if there is a Data Stage
933 //
934 switch (Direction) {
935
936 case EfiUsbDataIn:
937 case EfiUsbDataOut:
938 BufferSize = BufferLength;
939
940 DataPhaseStatus = Cbi0DataPhase (
941 UsbCbiDev,
942 &BufferSize,
943 DataBuffer,
944 Direction,
945 TimeOutInMilliSeconds
946 );
947 break;
948
949 case EfiUsbNoData:
950 break;
951 }
952
953 if (EFI_ERROR (DataPhaseStatus)) {
954 return EFI_DEVICE_ERROR;
955 }
956
957 //
958 // Status Phase
959 //
960 Status = Cbi0StatusPhase (
961 UsbCbiDev,
962 &InterruptDataBlock,
963 TimeOutInMilliSeconds
964 );
965 if (EFI_ERROR (Status)) {
966 return EFI_DEVICE_ERROR;
967 }
968
969 if (This->CommandProtocol != EFI_USB_SUBCLASS_UFI) {
970
971 if (InterruptDataBlock.bType == 0) {
972 //
973 // indicates command completion
974 //
975 switch (InterruptDataBlock.bValue & 0x03) {
976
977 case 0:
978 Status = EFI_SUCCESS;
979 break;
980
981 case 1:
982 Status = EFI_DEVICE_ERROR;
983 break;
984
985 case 2:
986 Status = Cbi0RecoveryReset (UsbCbiDev);
987 if (EFI_ERROR (Status)) {
988 UsbCbiDev->UsbIo->UsbPortReset (UsbCbiDev->UsbIo);
989 }
990
991 Status = EFI_DEVICE_ERROR;
992 break;
993
994 case 3:
995 Status = EFI_DEVICE_ERROR;
996 }
997 } else {
998 Status = DataPhaseStatus;
999 }
1000
1001 } else {
1002 //
1003 // UFI device, InterruptDataBlock.bType: ASC (Additional Sense Code)
1004 // InterruptDataBlock.bValue: ASCQ (Additional Snese Code Qualifier)
1005 //
1006 Status = DataPhaseStatus;
1007 }
1008
1009 return Status;
1010 }
1011
1012 VOID
1013 Cbi0ReportStatusCode (
1014 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1015 IN EFI_STATUS_CODE_TYPE CodeType,
1016 IN EFI_STATUS_CODE_VALUE Value
1017 )
1018 /*++
1019
1020 Routine Description:
1021 Report Status Code in Usb Cbi0 Driver
1022
1023 Arguments:
1024 DevicePath - Use this to get Device Path
1025 CodeType - Status Code Type
1026 CodeValue - Status Code Value
1027
1028 Returns:
1029 None
1030
1031 --*/
1032 {
1033
1034 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1035 CodeType,
1036 Value,
1037 DevicePath
1038 );
1039 }