]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c
1. Add NULL QH to set as QH header;
[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 EFI_USB_IO_PROTOCOL *UsbIo;
445
446 //
447 // Get our context back.
448 //
449 Status = gBS->OpenProtocol (
450 ControllerHandle,
451 &gEfiUsbAtapiProtocolGuid,
452 (VOID **) &BotAtapiProtocol,
453 This->DriverBindingHandle,
454 ControllerHandle,
455 EFI_OPEN_PROTOCOL_GET_PROTOCOL
456 );
457 if (EFI_ERROR (Status)) {
458 return EFI_UNSUPPORTED;
459 }
460
461 UsbBotDev = USB_BOT_DEVICE_FROM_THIS (BotAtapiProtocol);
462
463 //
464 // After installing Usb-Atapi protocol onto this handle
465 // it will be called by upper layer drivers such as Fat
466 //
467 UsbIo = UsbBotDev->UsbIo;
468
469 BotReportStatusCode (
470 UsbBotDev->DevicePath,
471 EFI_PROGRESS_CODE,
472 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE)
473 );
474
475 //
476 // Uninstall protocol
477 //
478 Status = gBS->UninstallProtocolInterface (
479 ControllerHandle,
480 &gEfiUsbAtapiProtocolGuid,
481 &UsbBotDev->UsbAtapiProtocol
482 );
483 if (EFI_ERROR (Status)) {
484 return Status;
485 }
486
487 Status = gBS->CloseProtocol (
488 ControllerHandle,
489 &gEfiUsbIoProtocolGuid,
490 This->DriverBindingHandle,
491 ControllerHandle
492 );
493 //
494 // Free all allocated resources
495 //
496 if (UsbBotDev->InterfaceDescriptor != NULL) {
497 gBS->FreePool (UsbBotDev->InterfaceDescriptor);
498 }
499
500 if (UsbBotDev->BulkInEndpointDescriptor != NULL) {
501 gBS->FreePool (UsbBotDev->BulkInEndpointDescriptor);
502 }
503
504 if (UsbBotDev->BulkOutEndpointDescriptor != NULL) {
505 gBS->FreePool (UsbBotDev->BulkOutEndpointDescriptor);
506 }
507
508 if (UsbBotDev->ControllerNameTable) {
509 FreeUnicodeStringTable (UsbBotDev->ControllerNameTable);
510 }
511
512 gBS->FreePool (UsbBotDev);
513
514 return Status;
515 }
516
517
518
519 STATIC
520 EFI_STATUS
521 ClearBulkInPipe (
522 IN USB_BOT_DEVICE *UsbBotDev
523 )
524 {
525 UINT32 Result;
526
527 return UsbClearEndpointHalt (
528 UsbBotDev->UsbIo,
529 UsbBotDev->BulkInEndpointDescriptor->EndpointAddress,
530 &Result
531 );
532 }
533
534
535 STATIC
536 EFI_STATUS
537 ClearBulkOutPipe (
538 IN USB_BOT_DEVICE *UsbBotDev
539 )
540 {
541 UINT32 Result;
542 return UsbClearEndpointHalt (
543 UsbBotDev->UsbIo,
544 UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress,
545 &Result
546 );
547 }
548
549 STATIC
550 EFI_STATUS
551 BotRecoveryReset (
552 IN USB_BOT_DEVICE *UsbBotDev
553 )
554 /*++
555
556 Routine Description:
557
558 Bot reset routine
559
560 Arguments:
561
562 UsbBotDev - USB_BOT_DEVICE pointer
563
564 Returns:
565 EFI_SUCCESS - Success the operation
566
567 --*/
568 {
569 EFI_STATUS Status;
570 EFI_USB_DEVICE_REQUEST Request;
571 UINT32 Result;
572 BotReportStatusCode (
573 UsbBotDev->DevicePath,
574 EFI_PROGRESS_CODE,
575 (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET)
576 );
577
578 ZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST));
579
580 //
581 // See BOT specification
582 //
583 Request.RequestType = 0x21;
584 Request.Request = 0xFF;
585
586 Status = UsbBotDev->UsbIo->UsbControlTransfer (
587 UsbBotDev->UsbIo,
588 &Request,
589 EfiUsbNoData,
590 TIMEOUT_VALUE,
591 NULL,
592 0,
593 &Result
594 );
595
596 gBS->Stall (100 * 1000);
597
598 ClearBulkInPipe (UsbBotDev);
599 ClearBulkOutPipe (UsbBotDev);
600
601 return Status;
602 }
603
604 //
605 // Bot Protocol Implementation
606 //
607 STATIC
608 EFI_STATUS
609 BotCommandPhase (
610 IN USB_BOT_DEVICE *UsbBotDev,
611 IN VOID *Command,
612 IN UINT8 CommandSize,
613 IN UINT32 DataTransferLength,
614 IN EFI_USB_DATA_DIRECTION Direction,
615 IN UINT16 Timeout
616 )
617 /*++
618
619 Routine Description:
620 Send ATAPI command through BOT interface.
621
622 Parameters:
623 UsbBotDev - USB_BOT_DEVICE
624 Command - command packet
625 CommandSize - Command size
626 DataTransferLength - Data Transfer Length
627 Direction - Data IN/OUT/NODATA
628 Timeout - Time out value in milliseconds
629 Return Values:
630 EFI_SUCCESS
631 Others
632
633 --*/
634 {
635 CBW cbw;
636 EFI_STATUS Status;
637 UINT32 Result;
638 EFI_USB_IO_PROTOCOL *UsbIo;
639 UINTN DataSize;
640
641 UsbIo = UsbBotDev->UsbIo;
642
643 ZeroMem (&cbw, sizeof (CBW));
644
645 //
646 // Fill the command block, detailed see BOT spec
647 //
648 cbw.dCBWSignature = CBWSIG;
649 cbw.dCBWTag = 0x01;
650 cbw.dCBWDataTransferLength = DataTransferLength;
651 switch (Direction) {
652 case EfiUsbDataOut:
653 case EfiUsbNoData:
654 cbw.bmCBWFlags = 0;
655 break;
656 case EfiUsbDataIn:
657 cbw.bmCBWFlags = 0x80;
658 break;
659 default:
660 break;
661 }
662 cbw.bCBWCBLength = CommandSize;
663
664 CopyMem (cbw.CBWCB, Command, CommandSize);
665
666 DataSize = sizeof (CBW);
667
668 Status = UsbIo->UsbBulkTransfer (
669 UsbIo,
670 UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress,
671 &cbw,
672 &DataSize,
673 Timeout,
674 &Result
675 );
676 return Status;
677 }
678
679 STATIC
680 EFI_STATUS
681 BotDataPhase (
682 IN USB_BOT_DEVICE *UsbBotDev,
683 IN UINTN *DataSize,
684 IN OUT VOID *DataBuffer,
685 IN EFI_USB_DATA_DIRECTION Direction,
686 IN UINT16 Timeout
687 )
688 /*++
689
690 Routine Description:
691 Get/Send Data through BOT interface
692
693 Parameters:
694 UsbBotDev - USB_BOT_DEVICE pointer
695 DataSize - Data size
696 DataBuffer - Data buffer pointer
697 Direction - IN/OUT/NODATA
698 Timeout - Time out value in milliseconds
699 Return Value:
700 EFI_SUCCESS
701 Others
702
703 --*/
704 {
705 EFI_STATUS Status;
706 UINT32 Result;
707 EFI_USB_IO_PROTOCOL *UsbIo;
708 UINT8 EndpointAddr;
709 UINT8 *BufferPtr;
710
711 UsbIo = UsbBotDev->UsbIo;
712 BufferPtr = (UINT8 *) DataBuffer;
713
714 //
715 // retrieve the the max packet length of the given endpoint
716 //
717 if (Direction == EfiUsbDataIn) {
718 EndpointAddr = UsbBotDev->BulkInEndpointDescriptor->EndpointAddress;
719 } else {
720 EndpointAddr = UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress;
721 }
722
723 Status = UsbIo->UsbBulkTransfer (
724 UsbIo,
725 EndpointAddr,
726 BufferPtr,
727 DataSize,
728 (UINT16)(Timeout),
729 &Result
730 );
731
732 if (EFI_ERROR (Status)) {
733 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
734 if (Direction == EfiUsbDataIn) {
735 DEBUG((gBOTErrorLevel, "BOT: Data IN Stall, ClearBulkInPipe\n"));
736 ClearBulkInPipe (UsbBotDev);
737 } else {
738 DEBUG((gBOTErrorLevel, "BOT: Data OUT Stall, ClearBulkInPipe\n"));
739 ClearBulkOutPipe (UsbBotDev);
740 }
741 }
742 // BotRecoveryReset (UsbBotDev);
743 }
744
745
746 return Status;
747 }
748
749 STATIC
750 EFI_STATUS
751 BotStatusPhase (
752 IN USB_BOT_DEVICE *UsbBotDev,
753 OUT UINT32 *DataResidue,
754 IN UINT16 Timeout
755 )
756 /*++
757
758 Routine Description:
759 Get transfer status through BOT interface
760
761 Parameters:
762 UsbBotDev - USB_BOT_DEVICE pointer
763 Timeout - Time out value in milliseconds
764 Return Value:
765 EFI_SUCCESS
766 Others
767
768 --*/
769 {
770 CSW csw;
771 EFI_STATUS Status;
772 EFI_USB_IO_PROTOCOL *UsbIo;
773 UINT8 EndpointAddr;
774 UINTN DataSize;
775 UINT32 Result;
776 UINT8 Index;
777
778 UsbIo = UsbBotDev->UsbIo;
779 EndpointAddr = UsbBotDev->BulkInEndpointDescriptor->EndpointAddress;
780
781
782 for (Index = 0; Index < 3; Index ++) {
783 ZeroMem (&csw, sizeof (CSW));
784 DataSize = sizeof (CSW);
785 Result = 0;
786
787 Status = UsbIo->UsbBulkTransfer (
788 UsbIo,
789 EndpointAddr,
790 &csw,
791 &DataSize,
792 Timeout,
793 &Result
794 );
795 if (EFI_ERROR (Status)) {
796 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
797 DEBUG((gBOTDebugLevel, "BOT: CSW Stall, ClearBulkInPipe\n"));
798 ClearBulkInPipe (UsbBotDev);
799 continue;
800 }
801 }
802
803 if (csw.dCSWSignature == CSWSIG) {
804 if (csw.bCSWStatus == 0 || csw.bCSWStatus == 0x01) {
805 if (DataResidue != NULL) {
806 *DataResidue = csw.dCSWDataResidue;
807 }
808 if (csw.bCSWStatus == 0x01) {
809 return EFI_DEVICE_ERROR;
810 }
811 break;
812 } else if (csw.bCSWStatus == 0x02) {
813 DEBUG((gBOTErrorLevel, "BOT: Bot Phase error\n"));
814 BotRecoveryReset (UsbBotDev);
815 }
816
817 }
818 }
819
820 if (Index == 3) {
821 return EFI_DEVICE_ERROR;
822 }
823
824 return EFI_SUCCESS;
825 }
826
827 //
828 // Usb Atapi Protocol implementation
829 //
830 EFI_STATUS
831 EFIAPI
832 BotAtapiCommand (
833 IN EFI_USB_ATAPI_PROTOCOL *This,
834 IN VOID *Command,
835 IN UINT8 CommandSize,
836 IN VOID *DataBuffer,
837 IN UINT32 BufferLength,
838 IN EFI_USB_DATA_DIRECTION Direction,
839 IN UINT16 TimeOutInMilliSeconds
840 )
841 /*++
842
843 Routine Description:
844 Send ATAPI command using BOT protocol.
845
846 Arguments:
847 This - Protocol instance pointer.
848 Command - Command buffer
849 CommandSize - Size of Command Buffer
850 DataBuffer - Data buffer
851 BufferLength - Length of Data buffer
852 Direction - Data direction of this command
853 TimeoutInMilliSeconds - Timeout value in ms
854
855 Returns:
856 EFI_SUCCESS - Command succeeded.
857 EFI_DEVICE_ERROR - Command failed.
858
859 --*/
860 {
861 EFI_STATUS Status;
862 EFI_STATUS BotDataStatus;
863 USB_BOT_DEVICE *UsbBotDev;
864 UINTN BufferSize;
865 UINT8 Index;
866 UINT32 DataResidue;
867
868 //
869 // Get the context
870 //
871 UsbBotDev = USB_BOT_DEVICE_FROM_THIS (This);
872 BotDataStatus = EFI_SUCCESS;
873 BufferSize = 0;
874
875 for (Index = 0; Index < 3; Index ++) {
876 //
877 // First send ATAPI command through Bot
878 //
879 Status = BotCommandPhase (
880 UsbBotDev,
881 Command,
882 CommandSize,
883 BufferLength,
884 Direction,
885 10 * 1000
886 );
887
888 if (EFI_ERROR (Status)) {
889 DEBUG((gBOTErrorLevel, "BotCommandPhase Fail\n"));
890 return Status;
891 }
892 //
893 // Send/Get Data if there is a Data Stage
894 //
895 switch (Direction) {
896
897 case EfiUsbDataIn:
898 case EfiUsbDataOut:
899 BufferSize = BufferLength;
900
901 BotDataStatus = BotDataPhase (
902 UsbBotDev,
903 &BufferSize,
904 DataBuffer,
905 Direction,
906 (UINT16) (TimeOutInMilliSeconds)
907 );
908
909
910 if (EFI_ERROR (BotDataStatus)) {
911 DEBUG((gBOTErrorLevel, "BotDataPhase Fail\n"));
912 }
913 break;
914
915 case EfiUsbNoData:
916 break;
917 }
918
919 DataResidue = 0;
920 //
921 // Status Phase
922 //
923 Status = BotStatusPhase (
924 UsbBotDev,
925 &DataResidue,
926 10 * 1000
927 );
928
929 if (EFI_ERROR (Status)) {
930 DEBUG((gBOTErrorLevel, "BotStatusPhase Fail\n"));
931 return Status;
932 }
933
934 if (!EFI_ERROR (BotDataStatus)) {
935 break;
936 }
937
938 }
939 return BotDataStatus;
940 }
941
942 EFI_STATUS
943 EFIAPI
944 BotMassStorageReset (
945 IN EFI_USB_ATAPI_PROTOCOL *This,
946 IN BOOLEAN ExtendedVerification
947 )
948 /*++
949
950 Routine Description:
951 Reset Bot Devices
952
953 Arguments:
954 This - Protocol instance pointer.
955 ExtendedVerification - TRUE if we need to do strictly reset.
956
957 Returns:
958 EFI_SUCCESS - Command succeeded.
959 EFI_DEVICE_ERROR - Command failed.
960
961 --*/
962 {
963 EFI_STATUS Status;
964 USB_BOT_DEVICE *UsbBotDev;
965 EFI_USB_IO_PROTOCOL *UsbIo;
966
967 UsbBotDev = USB_BOT_DEVICE_FROM_THIS (This);
968 UsbIo = UsbBotDev->UsbIo;
969
970 if (ExtendedVerification) {
971 //
972 // If we need to do strictly reset, reset its parent hub port
973 //
974 Status = UsbIo->UsbPortReset (UsbIo);
975 if (EFI_ERROR (Status)) {
976 return Status;
977 }
978 }
979
980 Status = BotRecoveryReset (UsbBotDev);
981
982 return Status;
983 }
984
985 VOID
986 BotReportStatusCode (
987 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
988 IN EFI_STATUS_CODE_TYPE CodeType,
989 IN EFI_STATUS_CODE_VALUE Value
990 )
991 /*++
992
993 Routine Description:
994 Report Status Code in Usb Bot Driver
995
996 Arguments:
997 DevicePath - Use this to get Device Path
998 CodeType - Status Code Type
999 CodeValue - Status Code Value
1000
1001 Returns:
1002 None
1003
1004 --*/
1005 {
1006 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1007 CodeType,
1008 Value,
1009 DevicePath
1010 );
1011 }