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