1. Sync definition of EFI_DEBUG_IMAGE_INFO with UEFI spec
[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 cbw.bmCBWFlags = (UINT8) ((Direction == EfiUsbDataIn) ? 0x80 : 0);
612 cbw.bCBWCBLength = CommandSize;
613
614 CopyMem (cbw.CBWCB, Command, CommandSize);
615
616 DataSize = sizeof (CBW);
617
618 Status = UsbIo->UsbBulkTransfer (
619 UsbIo,
620 UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress,
621 &cbw,
622 &DataSize,
623 Timeout,
624 &Result
625 );
626 return Status;
627 }
628
629 STATIC
630 EFI_STATUS
631 BotDataPhase (
632 IN USB_BOT_DEVICE *UsbBotDev,
633 IN UINTN *DataSize,
634 IN OUT VOID *DataBuffer,
635 IN EFI_USB_DATA_DIRECTION Direction,
636 IN UINT16 Timeout
637 )
638 /*++
639
640 Routine Description:
641 Get/Send Data through BOT interface
642
643 Parameters:
644 UsbBotDev - USB_BOT_DEVICE pointer
645 DataSize - Data size
646 DataBuffer - Data buffer pointer
647 Direction - IN/OUT/NODATA
648 Timeout - Time out value in milliseconds
649 Return Value:
650 EFI_SUCCESS
651 Others
652
653 --*/
654 {
655 EFI_STATUS Status;
656 UINT32 Result;
657 EFI_USB_IO_PROTOCOL *UsbIo;
658 UINT8 EndpointAddr;
659 UINT8 *BufferPtr;
660
661 UsbIo = UsbBotDev->UsbIo;
662 BufferPtr = (UINT8 *) DataBuffer;
663
664 //
665 // retrieve the the max packet length of the given endpoint
666 //
667 if (Direction == EfiUsbDataIn) {
668 EndpointAddr = UsbBotDev->BulkInEndpointDescriptor->EndpointAddress;
669 } else {
670 EndpointAddr = UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress;
671 }
672
673 Status = UsbIo->UsbBulkTransfer (
674 UsbIo,
675 EndpointAddr,
676 BufferPtr,
677 DataSize,
678 (UINT16)(Timeout),
679 &Result
680 );
681
682 if (EFI_ERROR (Status)) {
683 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
684 if (Direction == EfiUsbDataIn) {
685 DEBUG((gBOTErrorLevel, "BOT: Data IN Stall, ClearBulkInPipe\n"));
686 ClearBulkInPipe (UsbBotDev);
687 } else {
688 DEBUG((gBOTErrorLevel, "BOT: Data OUT Stall, ClearBulkInPipe\n"));
689 ClearBulkOutPipe (UsbBotDev);
690 }
691 }
692 // BotRecoveryReset (UsbBotDev);
693 }
694
695
696 return Status;
697 }
698
699 STATIC
700 EFI_STATUS
701 BotStatusPhase (
702 IN USB_BOT_DEVICE *UsbBotDev,
703 OUT UINT32 *DataResidue,
704 IN UINT16 Timeout
705 )
706 /*++
707
708 Routine Description:
709 Get transfer status through BOT interface
710
711 Parameters:
712 UsbBotDev - USB_BOT_DEVICE pointer
713 Timeout - Time out value in milliseconds
714 Return Value:
715 EFI_SUCCESS
716 Others
717
718 --*/
719 {
720 CSW csw;
721 EFI_STATUS Status;
722 EFI_USB_IO_PROTOCOL *UsbIo;
723 UINT8 EndpointAddr;
724 UINTN DataSize;
725 UINT32 Result;
726 UINT8 Index;
727
728 UsbIo = UsbBotDev->UsbIo;
729 EndpointAddr = UsbBotDev->BulkInEndpointDescriptor->EndpointAddress;
730
731
732 for (Index = 0; Index < 3; Index ++) {
733 ZeroMem (&csw, sizeof (CSW));
734 DataSize = sizeof (CSW);
735 Result = 0;
736
737 Status = UsbIo->UsbBulkTransfer (
738 UsbIo,
739 EndpointAddr,
740 &csw,
741 &DataSize,
742 Timeout,
743 &Result
744 );
745 if (EFI_ERROR (Status)) {
746 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
747 DEBUG((gBOTDebugLevel, "BOT: CSW Stall, ClearBulkInPipe\n"));
748 ClearBulkInPipe (UsbBotDev);
749 continue;
750 }
751 }
752
753 if (csw.dCSWSignature == CSWSIG) {
754 if (csw.bCSWStatus == 0 || csw.bCSWStatus == 0x01) {
755 if (DataResidue != NULL) {
756 *DataResidue = csw.dCSWDataResidue;
757 }
758 if (csw.bCSWStatus == 0x01) {
759 return EFI_DEVICE_ERROR;
760 }
761 break;
762 } else if (csw.bCSWStatus == 0x02) {
763 DEBUG((gBOTErrorLevel, "BOT: Bot Phase error\n"));
764 BotRecoveryReset (UsbBotDev);
765 }
766
767 }
768 }
769
770 if (Index == 3) {
771 return EFI_DEVICE_ERROR;
772 }
773
774 return EFI_SUCCESS;
775 }
776
777 //
778 // Usb Atapi Protocol implementation
779 //
780 EFI_STATUS
781 EFIAPI
782 BotAtapiCommand (
783 IN EFI_USB_ATAPI_PROTOCOL *This,
784 IN VOID *Command,
785 IN UINT8 CommandSize,
786 IN VOID *DataBuffer,
787 IN UINT32 BufferLength,
788 IN EFI_USB_DATA_DIRECTION Direction,
789 IN UINT16 TimeOutInMilliSeconds
790 )
791 /*++
792
793 Routine Description:
794 Send ATAPI command using BOT protocol.
795
796 Arguments:
797 This - Protocol instance pointer.
798 Command - Command buffer
799 CommandSize - Size of Command Buffer
800 DataBuffer - Data buffer
801 BufferLength - Length of Data buffer
802 Direction - Data direction of this command
803 TimeoutInMilliSeconds - Timeout value in ms
804
805 Returns:
806 EFI_SUCCESS - Command succeeded.
807 EFI_DEVICE_ERROR - Command failed.
808
809 --*/
810 {
811 EFI_STATUS Status;
812 EFI_STATUS BotDataStatus;
813 USB_BOT_DEVICE *UsbBotDev;
814 UINTN BufferSize;
815 UINT8 Index;
816 UINT32 DataResidue;
817
818 //
819 // Get the context
820 //
821 UsbBotDev = USB_BOT_DEVICE_FROM_THIS (This);
822 BotDataStatus = EFI_SUCCESS;
823 BufferSize = 0;
824
825 for (Index = 0; Index < 3; Index ++) {
826 //
827 // First send ATAPI command through Bot
828 //
829 Status = BotCommandPhase (
830 UsbBotDev,
831 Command,
832 CommandSize,
833 BufferLength,
834 Direction,
835 10 * 1000
836 );
837
838 if (EFI_ERROR (Status)) {
839 DEBUG((gBOTErrorLevel, "BotCommandPhase Fail\n"));
840 return Status;
841 }
842 //
843 // Send/Get Data if there is a Data Stage
844 //
845 switch (Direction) {
846
847 case EfiUsbDataIn:
848 case EfiUsbDataOut:
849 BufferSize = BufferLength;
850
851 BotDataStatus = BotDataPhase (
852 UsbBotDev,
853 &BufferSize,
854 DataBuffer,
855 Direction,
856 (UINT16) (TimeOutInMilliSeconds)
857 );
858
859
860 if (EFI_ERROR (BotDataStatus)) {
861 DEBUG((gBOTErrorLevel, "BotDataPhase Fail\n"));
862 }
863 break;
864
865 case EfiUsbNoData:
866 break;
867 }
868
869 DataResidue = 0;
870 //
871 // Status Phase
872 //
873 Status = BotStatusPhase (
874 UsbBotDev,
875 &DataResidue,
876 10 * 1000
877 );
878
879 if (EFI_ERROR (Status)) {
880 DEBUG((gBOTErrorLevel, "BotStatusPhase Fail\n"));
881 return Status;
882 }
883
884 if (!EFI_ERROR (BotDataStatus)) {
885 break;
886 }
887
888 }
889 return BotDataStatus;
890 }
891
892 EFI_STATUS
893 EFIAPI
894 BotMassStorageReset (
895 IN EFI_USB_ATAPI_PROTOCOL *This,
896 IN BOOLEAN ExtendedVerification
897 )
898 /*++
899
900 Routine Description:
901 Reset Bot Devices
902
903 Arguments:
904 This - Protocol instance pointer.
905 ExtendedVerification - TRUE if we need to do strictly reset.
906
907 Returns:
908 EFI_SUCCESS - Command succeeded.
909 EFI_DEVICE_ERROR - Command failed.
910
911 --*/
912 {
913 EFI_STATUS Status;
914 USB_BOT_DEVICE *UsbBotDev;
915 EFI_USB_IO_PROTOCOL *UsbIo;
916
917 UsbBotDev = USB_BOT_DEVICE_FROM_THIS (This);
918 UsbIo = UsbBotDev->UsbIo;
919
920 if (ExtendedVerification) {
921 //
922 // If we need to do strictly reset, reset its parent hub port
923 //
924 Status = UsbIo->UsbPortReset (UsbIo);
925 if (EFI_ERROR (Status)) {
926 return Status;
927 }
928 }
929
930 Status = BotRecoveryReset (UsbBotDev);
931
932 return Status;
933 }
934
935 STATIC
936 VOID
937 BotReportStatusCode (
938 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
939 IN EFI_STATUS_CODE_TYPE CodeType,
940 IN EFI_STATUS_CODE_VALUE Value
941 )
942 /*++
943
944 Routine Description:
945 Report Status Code in Usb Bot Driver
946
947 Arguments:
948 DevicePath - Use this to get Device Path
949 CodeType - Status Code Type
950 CodeValue - Status Code Value
951
952 Returns:
953 None
954
955 --*/
956 {
957 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
958 CodeType,
959 Value,
960 DevicePath
961 );
962 }