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