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