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