TianoCore EDK2 master
Loading...
Searching...
No Matches
Ehci.c
Go to the documentation of this file.
1
19#include "Ehci.h"
20
21//
22// Two arrays used to translate the EHCI port state (change)
23// to the UEFI protocol's port state (change).
24//
25USB_PORT_STATE_MAP mUsbPortStateMap[] = {
26 { PORTSC_CONN, USB_PORT_STAT_CONNECTION },
27 { PORTSC_ENABLED, USB_PORT_STAT_ENABLE },
28 { PORTSC_SUSPEND, USB_PORT_STAT_SUSPEND },
29 { PORTSC_OVERCUR, USB_PORT_STAT_OVERCURRENT },
30 { PORTSC_RESET, USB_PORT_STAT_RESET },
31 { PORTSC_POWER, USB_PORT_STAT_POWER },
32 { PORTSC_OWNER, USB_PORT_STAT_OWNER }
33};
34
35USB_PORT_STATE_MAP mUsbPortChangeMap[] = {
36 { PORTSC_CONN_CHANGE, USB_PORT_STAT_C_CONNECTION },
37 { PORTSC_ENABLE_CHANGE, USB_PORT_STAT_C_ENABLE },
38 { PORTSC_OVERCUR_CHANGE, USB_PORT_STAT_C_OVERCURRENT }
39};
40
42 gEhciDriverBinding = {
46 0x30,
47 NULL,
48 NULL
49};
50
65EFIAPI
68 OUT UINT8 *MaxSpeed,
69 OUT UINT8 *PortNumber,
70 OUT UINT8 *Is64BitCapable
71 )
72{
73 USB2_HC_DEV *Ehc;
74 EFI_TPL OldTpl;
75
76 if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {
77 return EFI_INVALID_PARAMETER;
78 }
79
80 OldTpl = gBS->RaiseTPL (EHC_TPL);
81 Ehc = EHC_FROM_THIS (This);
82
83 *MaxSpeed = EFI_USB_SPEED_HIGH;
84 *PortNumber = (UINT8)(Ehc->HcStructParams & HCSP_NPORTS);
85 *Is64BitCapable = (UINT8)Ehc->Support64BitDma;
86
87 DEBUG ((DEBUG_INFO, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));
88
89 gBS->RestoreTPL (OldTpl);
90 return EFI_SUCCESS;
91}
92
107EFIAPI
110 IN UINT16 Attributes
111 )
112{
113 USB2_HC_DEV *Ehc;
114 EFI_TPL OldTpl;
115 EFI_STATUS Status;
116
117 Ehc = EHC_FROM_THIS (This);
118
119 if (Ehc->DevicePath != NULL) {
120 //
121 // Report Status Code to indicate reset happens
122 //
125 (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),
126 Ehc->DevicePath
127 );
128 }
129
130 OldTpl = gBS->RaiseTPL (EHC_TPL);
131
132 switch (Attributes) {
133 case EFI_USB_HC_RESET_GLOBAL:
134 //
135 // Flow through, same behavior as Host Controller Reset
136 //
137 case EFI_USB_HC_RESET_HOST_CONTROLLER:
138 //
139 // Host Controller must be Halt when Reset it
140 //
141 if (EhcIsDebugPortInUse (Ehc, NULL)) {
142 Status = EFI_SUCCESS;
143 goto ON_EXIT;
144 }
145
146 if (!EhcIsHalt (Ehc)) {
147 Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
148
149 if (EFI_ERROR (Status)) {
150 Status = EFI_DEVICE_ERROR;
151 goto ON_EXIT;
152 }
153 }
154
155 //
156 // Clean up the asynchronous transfers, currently only
157 // interrupt supports asynchronous operation.
158 //
160 EhcAckAllInterrupt (Ehc);
161 EhcFreeSched (Ehc);
162
163 Status = EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
164
165 if (EFI_ERROR (Status)) {
166 goto ON_EXIT;
167 }
168
169 Status = EhcInitHC (Ehc);
170 break;
171
172 case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:
173 case EFI_USB_HC_RESET_HOST_WITH_DEBUG:
174 Status = EFI_UNSUPPORTED;
175 break;
176
177 default:
178 Status = EFI_INVALID_PARAMETER;
179 }
180
181ON_EXIT:
182 DEBUG ((DEBUG_INFO, "EhcReset: exit status %r\n", Status));
183 gBS->RestoreTPL (OldTpl);
184 return Status;
185}
186
201EFIAPI
204 OUT EFI_USB_HC_STATE *State
205 )
206{
207 EFI_TPL OldTpl;
208 USB2_HC_DEV *Ehc;
209
210 if (State == NULL) {
211 return EFI_INVALID_PARAMETER;
212 }
213
214 OldTpl = gBS->RaiseTPL (EHC_TPL);
215 Ehc = EHC_FROM_THIS (This);
216
217 if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
218 *State = EfiUsbHcStateHalt;
219 } else {
221 }
222
223 gBS->RestoreTPL (OldTpl);
224
225 DEBUG ((DEBUG_INFO, "EhcGetState: current state %d\n", *State));
226 return EFI_SUCCESS;
227}
228
242EFIAPI
245 IN EFI_USB_HC_STATE State
246 )
247{
248 USB2_HC_DEV *Ehc;
249 EFI_TPL OldTpl;
250 EFI_STATUS Status;
251 EFI_USB_HC_STATE CurState;
252
253 Status = EhcGetState (This, &CurState);
254
255 if (EFI_ERROR (Status)) {
256 return EFI_DEVICE_ERROR;
257 }
258
259 if (CurState == State) {
260 return EFI_SUCCESS;
261 }
262
263 OldTpl = gBS->RaiseTPL (EHC_TPL);
264 Ehc = EHC_FROM_THIS (This);
265
266 switch (State) {
268 Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
269 break;
270
272 if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR)) {
273 Status = EFI_DEVICE_ERROR;
274 break;
275 }
276
277 //
278 // Software must not write a one to this field unless the host controller
279 // is in the Halted state. Doing so will yield undefined results.
280 // refers to Spec[EHCI1.0-2.3.1]
281 //
282 if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
283 Status = EFI_DEVICE_ERROR;
284 break;
285 }
286
287 Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
288 break;
289
291 Status = EFI_UNSUPPORTED;
292 break;
293
294 default:
295 Status = EFI_INVALID_PARAMETER;
296 }
297
298 DEBUG ((DEBUG_INFO, "EhcSetState: exit status %r\n", Status));
299 gBS->RestoreTPL (OldTpl);
300 return Status;
301}
302
318EFIAPI
321 IN UINT8 PortNumber,
322 OUT EFI_USB_PORT_STATUS *PortStatus
323 )
324{
325 USB2_HC_DEV *Ehc;
326 EFI_TPL OldTpl;
327 UINT32 Offset;
328 UINT32 State;
329 UINT32 TotalPort;
330 UINTN Index;
331 UINTN MapSize;
332 EFI_STATUS Status;
333
334 if (PortStatus == NULL) {
335 return EFI_INVALID_PARAMETER;
336 }
337
338 OldTpl = gBS->RaiseTPL (EHC_TPL);
339
340 Ehc = EHC_FROM_THIS (This);
341 Status = EFI_SUCCESS;
342
343 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
344
345 if (PortNumber >= TotalPort) {
346 Status = EFI_INVALID_PARAMETER;
347 goto ON_EXIT;
348 }
349
350 Offset = (UINT32)(EHC_PORT_STAT_OFFSET + (4 * PortNumber));
351 PortStatus->PortStatus = 0;
352 PortStatus->PortChangeStatus = 0;
353
354 if (EhcIsDebugPortInUse (Ehc, &PortNumber)) {
355 goto ON_EXIT;
356 }
357
358 State = EhcReadOpReg (Ehc, Offset);
359
360 //
361 // Identify device speed. If in K state, it is low speed.
362 // If the port is enabled after reset, the device is of
363 // high speed. The USB bus driver should retrieve the actual
364 // port speed after reset.
365 //
366 if (EHC_BIT_IS_SET (State, PORTSC_LINESTATE_K)) {
367 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
368 } else if (EHC_BIT_IS_SET (State, PORTSC_ENABLED)) {
369 PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
370 }
371
372 //
373 // Convert the EHCI port/port change state to UEFI status
374 //
375 MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
376
377 for (Index = 0; Index < MapSize; Index++) {
378 if (EHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
379 PortStatus->PortStatus = (UINT16)(PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
380 }
381 }
382
383 MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
384
385 for (Index = 0; Index < MapSize; Index++) {
386 if (EHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
387 PortStatus->PortChangeStatus = (UINT16)(PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
388 }
389 }
390
391ON_EXIT:
392 gBS->RestoreTPL (OldTpl);
393 return Status;
394}
395
409EFIAPI
412 IN UINT8 PortNumber,
413 IN EFI_USB_PORT_FEATURE PortFeature
414 )
415{
416 USB2_HC_DEV *Ehc;
417 EFI_TPL OldTpl;
418 UINT32 Offset;
419 UINT32 State;
420 UINT32 TotalPort;
421 EFI_STATUS Status;
422
423 OldTpl = gBS->RaiseTPL (EHC_TPL);
424 Ehc = EHC_FROM_THIS (This);
425 Status = EFI_SUCCESS;
426
427 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
428
429 if (PortNumber >= TotalPort) {
430 Status = EFI_INVALID_PARAMETER;
431 goto ON_EXIT;
432 }
433
434 Offset = (UINT32)(EHC_PORT_STAT_OFFSET + (4 * PortNumber));
435 State = EhcReadOpReg (Ehc, Offset);
436
437 //
438 // Mask off the port status change bits, these bits are
439 // write clean bit
440 //
441 State &= ~PORTSC_CHANGE_MASK;
442
443 switch (PortFeature) {
444 case EfiUsbPortEnable:
445 //
446 // Sofeware can't set this bit, Port can only be enable by
447 // EHCI as a part of the reset and enable
448 //
449 State |= PORTSC_ENABLED;
450 EhcWriteOpReg (Ehc, Offset, State);
451 break;
452
453 case EfiUsbPortSuspend:
454 State |= PORTSC_SUSPEND;
455 EhcWriteOpReg (Ehc, Offset, State);
456 break;
457
458 case EfiUsbPortReset:
459 //
460 // Make sure Host Controller not halt before reset it
461 //
462 if (EhcIsHalt (Ehc)) {
463 Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
464
465 if (EFI_ERROR (Status)) {
466 DEBUG ((DEBUG_INFO, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status));
467 break;
468 }
469 }
470
471 //
472 // Set one to PortReset bit must also set zero to PortEnable bit
473 //
474 State |= PORTSC_RESET;
475 State &= ~PORTSC_ENABLED;
476 EhcWriteOpReg (Ehc, Offset, State);
477 break;
478
479 case EfiUsbPortPower:
480 //
481 // Set port power bit when PPC is 1
482 //
483 if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) {
484 State |= PORTSC_POWER;
485 EhcWriteOpReg (Ehc, Offset, State);
486 }
487
488 break;
489
490 case EfiUsbPortOwner:
491 State |= PORTSC_OWNER;
492 EhcWriteOpReg (Ehc, Offset, State);
493 break;
494
495 default:
496 Status = EFI_INVALID_PARAMETER;
497 }
498
499ON_EXIT:
500 DEBUG ((DEBUG_INFO, "EhcSetRootHubPortFeature: exit status %r\n", Status));
501
502 gBS->RestoreTPL (OldTpl);
503 return Status;
504}
505
522EFIAPI
525 IN UINT8 PortNumber,
526 IN EFI_USB_PORT_FEATURE PortFeature
527 )
528{
529 USB2_HC_DEV *Ehc;
530 EFI_TPL OldTpl;
531 UINT32 Offset;
532 UINT32 State;
533 UINT32 TotalPort;
534 EFI_STATUS Status;
535
536 OldTpl = gBS->RaiseTPL (EHC_TPL);
537 Ehc = EHC_FROM_THIS (This);
538 Status = EFI_SUCCESS;
539
540 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
541
542 if (PortNumber >= TotalPort) {
543 Status = EFI_INVALID_PARAMETER;
544 goto ON_EXIT;
545 }
546
547 Offset = EHC_PORT_STAT_OFFSET + (4 * PortNumber);
548 State = EhcReadOpReg (Ehc, Offset);
549 State &= ~PORTSC_CHANGE_MASK;
550
551 switch (PortFeature) {
552 case EfiUsbPortEnable:
553 //
554 // Clear PORT_ENABLE feature means disable port.
555 //
556 State &= ~PORTSC_ENABLED;
557 EhcWriteOpReg (Ehc, Offset, State);
558 break;
559
560 case EfiUsbPortSuspend:
561 //
562 // A write of zero to this bit is ignored by the host
563 // controller. The host controller will unconditionally
564 // set this bit to a zero when:
565 // 1. software sets the Forct Port Resume bit to a zero from a one.
566 // 2. software sets the Port Reset bit to a one frome a zero.
567 //
568 State &= ~PORSTSC_RESUME;
569 EhcWriteOpReg (Ehc, Offset, State);
570 break;
571
572 case EfiUsbPortReset:
573 //
574 // Clear PORT_RESET means clear the reset signal.
575 //
576 State &= ~PORTSC_RESET;
577 EhcWriteOpReg (Ehc, Offset, State);
578 break;
579
580 case EfiUsbPortOwner:
581 //
582 // Clear port owner means this port owned by EHC
583 //
584 State &= ~PORTSC_OWNER;
585 EhcWriteOpReg (Ehc, Offset, State);
586 break;
587
588 case EfiUsbPortConnectChange:
589 //
590 // Clear connect status change
591 //
592 State |= PORTSC_CONN_CHANGE;
593 EhcWriteOpReg (Ehc, Offset, State);
594 break;
595
596 case EfiUsbPortEnableChange:
597 //
598 // Clear enable status change
599 //
600 State |= PORTSC_ENABLE_CHANGE;
601 EhcWriteOpReg (Ehc, Offset, State);
602 break;
603
604 case EfiUsbPortOverCurrentChange:
605 //
606 // Clear PortOverCurrent change
607 //
608 State |= PORTSC_OVERCUR_CHANGE;
609 EhcWriteOpReg (Ehc, Offset, State);
610 break;
611
612 case EfiUsbPortPower:
613 //
614 // Clear port power bit when PPC is 1
615 //
616 if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) {
617 State &= ~PORTSC_POWER;
618 EhcWriteOpReg (Ehc, Offset, State);
619 }
620
621 break;
622 case EfiUsbPortSuspendChange:
623 case EfiUsbPortResetChange:
624 //
625 // Not supported or not related operation
626 //
627 break;
628
629 default:
630 Status = EFI_INVALID_PARAMETER;
631 break;
632 }
633
634ON_EXIT:
635 DEBUG ((DEBUG_INFO, "EhcClearRootHubPortFeature: exit status %r\n", Status));
636 gBS->RestoreTPL (OldTpl);
637 return Status;
638}
639
665EFIAPI
668 IN UINT8 DeviceAddress,
669 IN UINT8 DeviceSpeed,
670 IN UINTN MaximumPacketLength,
671 IN EFI_USB_DEVICE_REQUEST *Request,
672 IN EFI_USB_DATA_DIRECTION TransferDirection,
673 IN OUT VOID *Data,
674 IN OUT UINTN *DataLength,
675 IN UINTN TimeOut,
677 OUT UINT32 *TransferResult
678 )
679{
680 USB2_HC_DEV *Ehc;
681 URB *Urb;
682 EFI_TPL OldTpl;
683 UINT8 Endpoint;
684 EFI_STATUS Status;
685
686 //
687 // Validate parameters
688 //
689 if ((Request == NULL) || (TransferResult == NULL)) {
690 return EFI_INVALID_PARAMETER;
691 }
692
693 if ((TransferDirection != EfiUsbDataIn) &&
694 (TransferDirection != EfiUsbDataOut) &&
695 (TransferDirection != EfiUsbNoData))
696 {
697 return EFI_INVALID_PARAMETER;
698 }
699
700 if ((TransferDirection == EfiUsbNoData) &&
701 ((Data != NULL) || (*DataLength != 0)))
702 {
703 return EFI_INVALID_PARAMETER;
704 }
705
706 if ((TransferDirection != EfiUsbNoData) &&
707 ((Data == NULL) || (*DataLength == 0)))
708 {
709 return EFI_INVALID_PARAMETER;
710 }
711
712 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&
713 (MaximumPacketLength != 32) && (MaximumPacketLength != 64))
714 {
715 return EFI_INVALID_PARAMETER;
716 }
717
718 if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {
719 return EFI_INVALID_PARAMETER;
720 }
721
722 OldTpl = gBS->RaiseTPL (EHC_TPL);
723 Ehc = EHC_FROM_THIS (This);
724
725 Status = EFI_DEVICE_ERROR;
726 *TransferResult = EFI_USB_ERR_SYSTEM;
727
728 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
729 DEBUG ((DEBUG_ERROR, "EhcControlTransfer: HC halted at entrance\n"));
730
731 EhcAckAllInterrupt (Ehc);
732 goto ON_EXIT;
733 }
734
735 EhcAckAllInterrupt (Ehc);
736
737 //
738 // Create a new URB, insert it into the asynchronous
739 // schedule list, then poll the execution status.
740 //
741 //
742 // Encode the direction in address, although default control
743 // endpoint is bidirectional. EhcCreateUrb expects this
744 // combination of Ep addr and its direction.
745 //
746 Endpoint = (UINT8)(0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
747 Urb = EhcCreateUrb (
748 Ehc,
749 DeviceAddress,
750 Endpoint,
751 DeviceSpeed,
752 0,
753 MaximumPacketLength,
754 Translator,
755 EHC_CTRL_TRANSFER,
756 Request,
757 Data,
758 *DataLength,
759 NULL,
760 NULL,
761 1
762 );
763
764 if (Urb == NULL) {
765 DEBUG ((DEBUG_ERROR, "EhcControlTransfer: failed to create URB"));
766
767 Status = EFI_OUT_OF_RESOURCES;
768 goto ON_EXIT;
769 }
770
771 EhcLinkQhToAsync (Ehc, Urb->Qh);
772 Status = EhcExecTransfer (Ehc, Urb, TimeOut);
773 EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
774
775 //
776 // Get the status from URB. The result is updated in EhcCheckUrbResult
777 // which is called by EhcExecTransfer
778 //
779 *TransferResult = Urb->Result;
780 *DataLength = Urb->Completed;
781
782 if (*TransferResult == EFI_USB_NOERROR) {
783 Status = EFI_SUCCESS;
784 }
785
786 EhcAckAllInterrupt (Ehc);
787 EhcFreeUrb (Ehc, Urb);
788
789ON_EXIT:
790 Ehc->PciIo->Flush (Ehc->PciIo);
791 gBS->RestoreTPL (OldTpl);
792
793 if (EFI_ERROR (Status)) {
794 DEBUG ((DEBUG_ERROR, "EhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
795 }
796
797 return Status;
798}
799
831EFIAPI
834 IN UINT8 DeviceAddress,
835 IN UINT8 EndPointAddress,
836 IN UINT8 DeviceSpeed,
837 IN UINTN MaximumPacketLength,
838 IN UINT8 DataBuffersNumber,
839 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
840 IN OUT UINTN *DataLength,
841 IN OUT UINT8 *DataToggle,
842 IN UINTN TimeOut,
844 OUT UINT32 *TransferResult
845 )
846{
847 USB2_HC_DEV *Ehc;
848 URB *Urb;
849 EFI_TPL OldTpl;
850 EFI_STATUS Status;
851 UINTN DebugErrorLevel;
852
853 //
854 // Validate the parameters
855 //
856 if ((DataLength == NULL) || (*DataLength == 0) ||
857 (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL))
858 {
859 return EFI_INVALID_PARAMETER;
860 }
861
862 if ((*DataToggle != 0) && (*DataToggle != 1)) {
863 return EFI_INVALID_PARAMETER;
864 }
865
866 if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
867 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
868 ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512)))
869 {
870 return EFI_INVALID_PARAMETER;
871 }
872
873 OldTpl = gBS->RaiseTPL (EHC_TPL);
874 Ehc = EHC_FROM_THIS (This);
875
876 *TransferResult = EFI_USB_ERR_SYSTEM;
877 Status = EFI_DEVICE_ERROR;
878
879 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
880 DEBUG ((DEBUG_ERROR, "EhcBulkTransfer: HC is halted\n"));
881
882 EhcAckAllInterrupt (Ehc);
883 goto ON_EXIT;
884 }
885
886 EhcAckAllInterrupt (Ehc);
887
888 //
889 // Create a new URB, insert it into the asynchronous
890 // schedule list, then poll the execution status.
891 //
892 Urb = EhcCreateUrb (
893 Ehc,
894 DeviceAddress,
895 EndPointAddress,
896 DeviceSpeed,
897 *DataToggle,
898 MaximumPacketLength,
899 Translator,
900 EHC_BULK_TRANSFER,
901 NULL,
902 Data[0],
903 *DataLength,
904 NULL,
905 NULL,
906 1
907 );
908
909 if (Urb == NULL) {
910 DEBUG ((DEBUG_ERROR, "EhcBulkTransfer: failed to create URB\n"));
911
912 Status = EFI_OUT_OF_RESOURCES;
913 goto ON_EXIT;
914 }
915
916 EhcLinkQhToAsync (Ehc, Urb->Qh);
917 Status = EhcExecTransfer (Ehc, Urb, TimeOut);
918 EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
919
920 *TransferResult = Urb->Result;
921 *DataLength = Urb->Completed;
922 *DataToggle = Urb->DataToggle;
923
924 if (*TransferResult == EFI_USB_NOERROR) {
925 Status = EFI_SUCCESS;
926 }
927
928 EhcAckAllInterrupt (Ehc);
929 EhcFreeUrb (Ehc, Urb);
930
931ON_EXIT:
932 Ehc->PciIo->Flush (Ehc->PciIo);
933 gBS->RestoreTPL (OldTpl);
934
935 if (EFI_ERROR (Status)) {
936 if (Status == EFI_TIMEOUT) {
937 DebugErrorLevel = DEBUG_VERBOSE;
938 } else {
939 DebugErrorLevel = DEBUG_ERROR;
940 }
941
942 DEBUG ((DebugErrorLevel, "EhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
943 }
944
945 return Status;
946}
947
978EFIAPI
981 IN UINT8 DeviceAddress,
982 IN UINT8 EndPointAddress,
983 IN UINT8 DeviceSpeed,
984 IN UINTN MaximumPacketLength,
985 IN BOOLEAN IsNewTransfer,
986 IN OUT UINT8 *DataToggle,
987 IN UINTN PollingInterval,
988 IN UINTN DataLength,
990 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
991 IN VOID *Context OPTIONAL
992 )
993{
994 USB2_HC_DEV *Ehc;
995 URB *Urb;
996 EFI_TPL OldTpl;
997 EFI_STATUS Status;
998
999 //
1000 // Validate parameters
1001 //
1002 if (!EHCI_IS_DATAIN (EndPointAddress)) {
1003 return EFI_INVALID_PARAMETER;
1004 }
1005
1006 if (IsNewTransfer) {
1007 if (DataLength == 0) {
1008 return EFI_INVALID_PARAMETER;
1009 }
1010
1011 if ((*DataToggle != 1) && (*DataToggle != 0)) {
1012 return EFI_INVALID_PARAMETER;
1013 }
1014
1015 if ((PollingInterval > 255) || (PollingInterval < 1)) {
1016 return EFI_INVALID_PARAMETER;
1017 }
1018 }
1019
1020 OldTpl = gBS->RaiseTPL (EHC_TPL);
1021 Ehc = EHC_FROM_THIS (This);
1022
1023 //
1024 // Delete Async interrupt transfer request. DataToggle will return
1025 // the next data toggle to use.
1026 //
1027 if (!IsNewTransfer) {
1028 Status = EhciDelAsyncIntTransfer (Ehc, DeviceAddress, EndPointAddress, DataToggle);
1029
1030 DEBUG ((DEBUG_INFO, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status));
1031 goto ON_EXIT;
1032 }
1033
1034 Status = EFI_SUCCESS;
1035
1036 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
1037 DEBUG ((DEBUG_ERROR, "EhcAsyncInterruptTransfer: HC is halt\n"));
1038 EhcAckAllInterrupt (Ehc);
1039
1040 Status = EFI_DEVICE_ERROR;
1041 goto ON_EXIT;
1042 }
1043
1044 EhcAckAllInterrupt (Ehc);
1045
1047 Ehc,
1048 DeviceAddress,
1049 EndPointAddress,
1050 DeviceSpeed,
1051 *DataToggle,
1052 MaximumPacketLength,
1053 Translator,
1054 DataLength,
1055 CallBackFunction,
1056 Context,
1057 PollingInterval
1058 );
1059
1060 if (Urb == NULL) {
1061 Status = EFI_OUT_OF_RESOURCES;
1062 goto ON_EXIT;
1063 }
1064
1065ON_EXIT:
1066 Ehc->PciIo->Flush (Ehc->PciIo);
1067 gBS->RestoreTPL (OldTpl);
1068
1069 return Status;
1070}
1071
1100EFIAPI
1103 IN UINT8 DeviceAddress,
1104 IN UINT8 EndPointAddress,
1105 IN UINT8 DeviceSpeed,
1106 IN UINTN MaximumPacketLength,
1107 IN OUT VOID *Data,
1108 IN OUT UINTN *DataLength,
1109 IN OUT UINT8 *DataToggle,
1110 IN UINTN TimeOut,
1112 OUT UINT32 *TransferResult
1113 )
1114{
1115 USB2_HC_DEV *Ehc;
1116 EFI_TPL OldTpl;
1117 URB *Urb;
1118 EFI_STATUS Status;
1119
1120 //
1121 // Validates parameters
1122 //
1123 if ((DataLength == NULL) || (*DataLength == 0) ||
1124 (Data == NULL) || (TransferResult == NULL))
1125 {
1126 return EFI_INVALID_PARAMETER;
1127 }
1128
1129 if ((*DataToggle != 1) && (*DataToggle != 0)) {
1130 return EFI_INVALID_PARAMETER;
1131 }
1132
1133 if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) ||
1134 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
1135 ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072)))
1136 {
1137 return EFI_INVALID_PARAMETER;
1138 }
1139
1140 OldTpl = gBS->RaiseTPL (EHC_TPL);
1141 Ehc = EHC_FROM_THIS (This);
1142
1143 *TransferResult = EFI_USB_ERR_SYSTEM;
1144 Status = EFI_DEVICE_ERROR;
1145
1146 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
1147 DEBUG ((DEBUG_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));
1148
1149 EhcAckAllInterrupt (Ehc);
1150 goto ON_EXIT;
1151 }
1152
1153 EhcAckAllInterrupt (Ehc);
1154
1155 Urb = EhcCreateUrb (
1156 Ehc,
1157 DeviceAddress,
1158 EndPointAddress,
1159 DeviceSpeed,
1160 *DataToggle,
1161 MaximumPacketLength,
1162 Translator,
1163 EHC_INT_TRANSFER_SYNC,
1164 NULL,
1165 Data,
1166 *DataLength,
1167 NULL,
1168 NULL,
1169 1
1170 );
1171
1172 if (Urb == NULL) {
1173 DEBUG ((DEBUG_ERROR, "EhcSyncInterruptTransfer: failed to create URB\n"));
1174
1175 Status = EFI_OUT_OF_RESOURCES;
1176 goto ON_EXIT;
1177 }
1178
1179 EhcLinkQhToPeriod (Ehc, Urb->Qh);
1180 Status = EhcExecTransfer (Ehc, Urb, TimeOut);
1181 EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);
1182
1183 *TransferResult = Urb->Result;
1184 *DataLength = Urb->Completed;
1185 *DataToggle = Urb->DataToggle;
1186
1187 if (*TransferResult == EFI_USB_NOERROR) {
1188 Status = EFI_SUCCESS;
1189 }
1190
1191 EhcFreeUrb (Ehc, Urb);
1192ON_EXIT:
1193 Ehc->PciIo->Flush (Ehc->PciIo);
1194 gBS->RestoreTPL (OldTpl);
1195
1196 if (EFI_ERROR (Status)) {
1197 DEBUG ((DEBUG_ERROR, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
1198 }
1199
1200 return Status;
1201}
1202
1225EFIAPI
1228 IN UINT8 DeviceAddress,
1229 IN UINT8 EndPointAddress,
1230 IN UINT8 DeviceSpeed,
1231 IN UINTN MaximumPacketLength,
1232 IN UINT8 DataBuffersNumber,
1233 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
1234 IN UINTN DataLength,
1236 OUT UINT32 *TransferResult
1237 )
1238{
1239 return EFI_UNSUPPORTED;
1240}
1241
1266EFIAPI
1269 IN UINT8 DeviceAddress,
1270 IN UINT8 EndPointAddress,
1271 IN UINT8 DeviceSpeed,
1272 IN UINTN MaximumPacketLength,
1273 IN UINT8 DataBuffersNumber,
1274 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
1275 IN UINTN DataLength,
1277 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
1278 IN VOID *Context
1279 )
1280{
1281 return EFI_UNSUPPORTED;
1282}
1283
1295EFIAPI
1297 IN EFI_HANDLE ImageHandle,
1298 IN EFI_SYSTEM_TABLE *SystemTable
1299 )
1300{
1302 ImageHandle,
1303 SystemTable,
1304 &gEhciDriverBinding,
1305 ImageHandle,
1306 &gEhciComponentName,
1307 &gEhciComponentName2
1308 );
1309}
1310
1325EFIAPI
1328 IN EFI_HANDLE Controller,
1329 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1330 )
1331{
1332 EFI_STATUS Status;
1333 EFI_PCI_IO_PROTOCOL *PciIo;
1334 USB_CLASSC UsbClassCReg;
1335
1336 //
1337 // Test whether there is PCI IO Protocol attached on the controller handle.
1338 //
1339 Status = gBS->OpenProtocol (
1340 Controller,
1341 &gEfiPciIoProtocolGuid,
1342 (VOID **)&PciIo,
1343 This->DriverBindingHandle,
1344 Controller,
1345 EFI_OPEN_PROTOCOL_BY_DRIVER
1346 );
1347
1348 if (EFI_ERROR (Status)) {
1349 return EFI_UNSUPPORTED;
1350 }
1351
1352 Status = PciIo->Pci.Read (
1353 PciIo,
1354 EfiPciIoWidthUint8,
1355 PCI_CLASSCODE_OFFSET,
1356 sizeof (USB_CLASSC) / sizeof (UINT8),
1357 &UsbClassCReg
1358 );
1359
1360 if (EFI_ERROR (Status)) {
1361 Status = EFI_UNSUPPORTED;
1362 goto ON_EXIT;
1363 }
1364
1365 //
1366 // Test whether the controller belongs to Ehci type
1367 //
1368 if ( (UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB)
1369 || ((UsbClassCReg.ProgInterface != PCI_IF_EHCI) && (UsbClassCReg.ProgInterface != PCI_IF_UHCI) && (UsbClassCReg.ProgInterface != PCI_IF_OHCI)))
1370 {
1371 Status = EFI_UNSUPPORTED;
1372 }
1373
1374ON_EXIT:
1375 gBS->CloseProtocol (
1376 Controller,
1377 &gEfiPciIoProtocolGuid,
1378 This->DriverBindingHandle,
1379 Controller
1380 );
1381
1382 return Status;
1383}
1384
1396 IN USB2_HC_DEV *Ehc
1397 )
1398{
1399 EFI_PCI_IO_PROTOCOL *PciIo;
1400 UINT16 PciStatus;
1401 UINT8 CapabilityPtr;
1402 UINT8 CapabilityId;
1403 UINT16 DebugPort;
1404 EFI_STATUS Status;
1405
1406 ASSERT (Ehc->PciIo != NULL);
1407 PciIo = Ehc->PciIo;
1408
1409 //
1410 // Detect if the EHCI host controller support Capaility Pointer.
1411 //
1412 Status = PciIo->Pci.Read (
1413 PciIo,
1414 EfiPciIoWidthUint8,
1415 PCI_PRIMARY_STATUS_OFFSET,
1416 sizeof (UINT16),
1417 &PciStatus
1418 );
1419
1420 if (EFI_ERROR (Status)) {
1421 return Status;
1422 }
1423
1424 if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {
1425 //
1426 // The Pci Device Doesn't Support Capability Pointer.
1427 //
1428 return EFI_UNSUPPORTED;
1429 }
1430
1431 //
1432 // Get Pointer To Capability List
1433 //
1434 Status = PciIo->Pci.Read (
1435 PciIo,
1436 EfiPciIoWidthUint8,
1437 PCI_CAPBILITY_POINTER_OFFSET,
1438 1,
1439 &CapabilityPtr
1440 );
1441
1442 if (EFI_ERROR (Status)) {
1443 return Status;
1444 }
1445
1446 //
1447 // Find Capability ID 0xA, Which Is For Debug Port
1448 //
1449 while (CapabilityPtr != 0) {
1450 Status = PciIo->Pci.Read (
1451 PciIo,
1452 EfiPciIoWidthUint8,
1453 CapabilityPtr,
1454 1,
1455 &CapabilityId
1456 );
1457
1458 if (EFI_ERROR (Status)) {
1459 return Status;
1460 }
1461
1462 if (CapabilityId == EHC_DEBUG_PORT_CAP_ID) {
1463 break;
1464 }
1465
1466 Status = PciIo->Pci.Read (
1467 PciIo,
1468 EfiPciIoWidthUint8,
1469 CapabilityPtr + 1,
1470 1,
1471 &CapabilityPtr
1472 );
1473
1474 if (EFI_ERROR (Status)) {
1475 return Status;
1476 }
1477 }
1478
1479 //
1480 // No Debug Port Capability Found
1481 //
1482 if (CapabilityPtr == 0) {
1483 return EFI_UNSUPPORTED;
1484 }
1485
1486 //
1487 // Get The Base Address Of Debug Port Register In Debug Port Capability Register
1488 //
1489 Status = PciIo->Pci.Read (
1490 Ehc->PciIo,
1491 EfiPciIoWidthUint8,
1492 CapabilityPtr + 2,
1493 sizeof (UINT16),
1494 &DebugPort
1495 );
1496
1497 if (EFI_ERROR (Status)) {
1498 return Status;
1499 }
1500
1501 Ehc->DebugPortOffset = DebugPort & 0x1FFF;
1502 Ehc->DebugPortBarNum = (UINT8)((DebugPort >> 13) - 1);
1503 Ehc->DebugPortNum = (UINT8)((Ehc->HcStructParams & 0x00F00000) >> 20);
1504
1505 return EFI_SUCCESS;
1506}
1507
1521 IN EFI_PCI_IO_PROTOCOL *PciIo,
1522 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1523 IN UINT64 OriginalPciAttributes
1524 )
1525{
1526 USB2_HC_DEV *Ehc;
1527 EFI_STATUS Status;
1528
1529 Ehc = AllocateZeroPool (sizeof (USB2_HC_DEV));
1530
1531 if (Ehc == NULL) {
1532 return NULL;
1533 }
1534
1535 //
1536 // Init EFI_USB2_HC_PROTOCOL interface and private data structure
1537 //
1538 Ehc->Signature = USB2_HC_DEV_SIGNATURE;
1539
1540 Ehc->Usb2Hc.GetCapability = EhcGetCapability;
1541 Ehc->Usb2Hc.Reset = EhcReset;
1542 Ehc->Usb2Hc.GetState = EhcGetState;
1543 Ehc->Usb2Hc.SetState = EhcSetState;
1544 Ehc->Usb2Hc.ControlTransfer = EhcControlTransfer;
1545 Ehc->Usb2Hc.BulkTransfer = EhcBulkTransfer;
1546 Ehc->Usb2Hc.AsyncInterruptTransfer = EhcAsyncInterruptTransfer;
1547 Ehc->Usb2Hc.SyncInterruptTransfer = EhcSyncInterruptTransfer;
1548 Ehc->Usb2Hc.IsochronousTransfer = EhcIsochronousTransfer;
1549 Ehc->Usb2Hc.AsyncIsochronousTransfer = EhcAsyncIsochronousTransfer;
1550 Ehc->Usb2Hc.GetRootHubPortStatus = EhcGetRootHubPortStatus;
1551 Ehc->Usb2Hc.SetRootHubPortFeature = EhcSetRootHubPortFeature;
1552 Ehc->Usb2Hc.ClearRootHubPortFeature = EhcClearRootHubPortFeature;
1553 Ehc->Usb2Hc.MajorRevision = 0x2;
1554 Ehc->Usb2Hc.MinorRevision = 0x0;
1555
1556 Ehc->PciIo = PciIo;
1557 Ehc->DevicePath = DevicePath;
1558 Ehc->OriginalPciAttributes = OriginalPciAttributes;
1559
1560 InitializeListHead (&Ehc->AsyncIntTransfers);
1561
1562 Ehc->HcStructParams = EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET);
1563 Ehc->HcCapParams = EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET);
1564 Ehc->CapLen = EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET) & 0x0FF;
1565
1566 DEBUG ((DEBUG_INFO, "EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen));
1567
1568 //
1569 // EHCI Controllers with a CapLen of 0 are ignored.
1570 //
1571 if (Ehc->CapLen == 0) {
1572 gBS->FreePool (Ehc);
1573 return NULL;
1574 }
1575
1577
1578 //
1579 // Create AsyncRequest Polling Timer
1580 //
1581 Status = gBS->CreateEvent (
1582 EVT_TIMER | EVT_NOTIFY_SIGNAL,
1583 TPL_NOTIFY,
1585 Ehc,
1586 &Ehc->PollTimer
1587 );
1588
1589 if (EFI_ERROR (Status)) {
1590 gBS->FreePool (Ehc);
1591 return NULL;
1592 }
1593
1594 return Ehc;
1595}
1596
1604VOID
1605EFIAPI
1607 EFI_EVENT Event,
1608 VOID *Context
1609 )
1610
1611{
1612 USB2_HC_DEV *Ehc;
1613
1614 Ehc = (USB2_HC_DEV *)Context;
1615
1616 //
1617 // Reset the Host Controller
1618 //
1619 EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
1620}
1621
1636EFIAPI
1639 IN EFI_HANDLE Controller,
1640 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1641 )
1642{
1643 EFI_STATUS Status;
1644 USB2_HC_DEV *Ehc;
1645 EFI_PCI_IO_PROTOCOL *PciIo;
1646 EFI_PCI_IO_PROTOCOL *Instance;
1647 UINT64 Supports;
1648 UINT64 OriginalPciAttributes;
1649 BOOLEAN PciAttributesSaved;
1650 USB_CLASSC UsbClassCReg;
1651 EFI_HANDLE *HandleBuffer;
1652 UINTN NumberOfHandles;
1653 UINTN Index;
1654 UINTN CompanionSegmentNumber;
1655 UINTN CompanionBusNumber;
1656 UINTN CompanionDeviceNumber;
1657 UINTN CompanionFunctionNumber;
1658 UINTN EhciSegmentNumber;
1659 UINTN EhciBusNumber;
1660 UINTN EhciDeviceNumber;
1661 UINTN EhciFunctionNumber;
1662 EFI_DEVICE_PATH_PROTOCOL *HcDevicePath;
1663
1664 //
1665 // Open the PciIo Protocol, then enable the USB host controller
1666 //
1667 Status = gBS->OpenProtocol (
1668 Controller,
1669 &gEfiPciIoProtocolGuid,
1670 (VOID **)&PciIo,
1671 This->DriverBindingHandle,
1672 Controller,
1673 EFI_OPEN_PROTOCOL_BY_DRIVER
1674 );
1675
1676 if (EFI_ERROR (Status)) {
1677 return Status;
1678 }
1679
1680 //
1681 // Open Device Path Protocol for on USB host controller
1682 //
1683 HcDevicePath = NULL;
1684 Status = gBS->OpenProtocol (
1685 Controller,
1686 &gEfiDevicePathProtocolGuid,
1687 (VOID **)&HcDevicePath,
1688 This->DriverBindingHandle,
1689 Controller,
1690 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1691 );
1692
1693 PciAttributesSaved = FALSE;
1694 //
1695 // Save original PCI attributes
1696 //
1697 Status = PciIo->Attributes (
1698 PciIo,
1700 0,
1701 &OriginalPciAttributes
1702 );
1703
1704 if (EFI_ERROR (Status)) {
1705 goto CLOSE_PCIIO;
1706 }
1707
1708 PciAttributesSaved = TRUE;
1709
1710 Status = PciIo->Attributes (
1711 PciIo,
1713 0,
1714 &Supports
1715 );
1716 if (!EFI_ERROR (Status)) {
1717 Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
1718 Status = PciIo->Attributes (
1719 PciIo,
1721 Supports,
1722 NULL
1723 );
1724 }
1725
1726 if (EFI_ERROR (Status)) {
1727 DEBUG ((DEBUG_ERROR, "EhcDriverBindingStart: failed to enable controller\n"));
1728 goto CLOSE_PCIIO;
1729 }
1730
1731 //
1732 // Get the Pci device class code.
1733 //
1734 Status = PciIo->Pci.Read (
1735 PciIo,
1736 EfiPciIoWidthUint8,
1737 PCI_CLASSCODE_OFFSET,
1738 sizeof (USB_CLASSC) / sizeof (UINT8),
1739 &UsbClassCReg
1740 );
1741
1742 if (EFI_ERROR (Status)) {
1743 Status = EFI_UNSUPPORTED;
1744 goto CLOSE_PCIIO;
1745 }
1746
1747 //
1748 // Determine if the device is UHCI or OHCI host controller or not. If yes, then find out the
1749 // companion usb ehci host controller and force EHCI driver get attached to it before
1750 // UHCI or OHCI driver attaches to UHCI or OHCI host controller.
1751 //
1752 if (((UsbClassCReg.ProgInterface == PCI_IF_UHCI) || (UsbClassCReg.ProgInterface == PCI_IF_OHCI)) &&
1753 (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
1754 (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB))
1755 {
1756 Status = PciIo->GetLocation (
1757 PciIo,
1758 &CompanionSegmentNumber,
1759 &CompanionBusNumber,
1760 &CompanionDeviceNumber,
1761 &CompanionFunctionNumber
1762 );
1763 if (EFI_ERROR (Status)) {
1764 goto CLOSE_PCIIO;
1765 }
1766
1767 Status = gBS->LocateHandleBuffer (
1768 ByProtocol,
1769 &gEfiPciIoProtocolGuid,
1770 NULL,
1771 &NumberOfHandles,
1772 &HandleBuffer
1773 );
1774 if (EFI_ERROR (Status)) {
1775 goto CLOSE_PCIIO;
1776 }
1777
1778 for (Index = 0; Index < NumberOfHandles; Index++) {
1779 //
1780 // Get the device path on this handle
1781 //
1782 Status = gBS->HandleProtocol (
1783 HandleBuffer[Index],
1784 &gEfiPciIoProtocolGuid,
1785 (VOID **)&Instance
1786 );
1787 ASSERT_EFI_ERROR (Status);
1788
1789 Status = Instance->Pci.Read (
1790 Instance,
1791 EfiPciIoWidthUint8,
1792 PCI_CLASSCODE_OFFSET,
1793 sizeof (USB_CLASSC) / sizeof (UINT8),
1794 &UsbClassCReg
1795 );
1796
1797 if (EFI_ERROR (Status)) {
1798 Status = EFI_UNSUPPORTED;
1799 goto CLOSE_PCIIO;
1800 }
1801
1802 if ((UsbClassCReg.ProgInterface == PCI_IF_EHCI) &&
1803 (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
1804 (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB))
1805 {
1806 Status = Instance->GetLocation (
1807 Instance,
1808 &EhciSegmentNumber,
1809 &EhciBusNumber,
1810 &EhciDeviceNumber,
1811 &EhciFunctionNumber
1812 );
1813 if (EFI_ERROR (Status)) {
1814 goto CLOSE_PCIIO;
1815 }
1816
1817 //
1818 // Currently, the judgment on the companion usb host controller is through the
1819 // same bus number, which may vary on different platform.
1820 //
1821 if (EhciBusNumber == CompanionBusNumber) {
1822 gBS->CloseProtocol (
1823 Controller,
1824 &gEfiPciIoProtocolGuid,
1825 This->DriverBindingHandle,
1826 Controller
1827 );
1828 EhcDriverBindingStart (This, HandleBuffer[Index], NULL);
1829 }
1830 }
1831 }
1832
1833 Status = EFI_NOT_FOUND;
1834 goto CLOSE_PCIIO;
1835 }
1836
1837 //
1838 // Create then install USB2_HC_PROTOCOL
1839 //
1840 Ehc = EhcCreateUsb2Hc (PciIo, HcDevicePath, OriginalPciAttributes);
1841
1842 if (Ehc == NULL) {
1843 DEBUG ((DEBUG_ERROR, "EhcDriverBindingStart: failed to create USB2_HC\n"));
1844
1845 Status = EFI_OUT_OF_RESOURCES;
1846 goto CLOSE_PCIIO;
1847 }
1848
1849 //
1850 // Enable 64-bit DMA support in the PCI layer if this controller
1851 // supports it.
1852 //
1853 if (EHC_BIT_IS_SET (Ehc->HcCapParams, HCCP_64BIT)) {
1854 Status = PciIo->Attributes (
1855 PciIo,
1858 NULL
1859 );
1860 if (!EFI_ERROR (Status)) {
1861 Ehc->Support64BitDma = TRUE;
1862 } else {
1863 DEBUG ((
1864 DEBUG_WARN,
1865 "%a: failed to enable 64-bit DMA on 64-bit capable controller @ %p (%r)\n",
1866 __func__,
1867 Controller,
1868 Status
1869 ));
1870 }
1871 }
1872
1873 Status = gBS->InstallProtocolInterface (
1874 &Controller,
1875 &gEfiUsb2HcProtocolGuid,
1877 &Ehc->Usb2Hc
1878 );
1879
1880 if (EFI_ERROR (Status)) {
1881 DEBUG ((DEBUG_ERROR, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
1882 goto FREE_POOL;
1883 }
1884
1885 //
1886 // Robustnesss improvement such as for Duet platform
1887 // Default is not required.
1888 //
1889 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
1891 }
1892
1893 if (!EhcIsDebugPortInUse (Ehc, NULL)) {
1894 EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
1895 }
1896
1897 Status = EhcInitHC (Ehc);
1898
1899 if (EFI_ERROR (Status)) {
1900 DEBUG ((DEBUG_ERROR, "EhcDriverBindingStart: failed to init host controller\n"));
1901 goto UNINSTALL_USBHC;
1902 }
1903
1904 //
1905 // Start the asynchronous interrupt monitor
1906 //
1907 Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL);
1908
1909 if (EFI_ERROR (Status)) {
1910 DEBUG ((DEBUG_ERROR, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
1911
1912 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
1913 goto UNINSTALL_USBHC;
1914 }
1915
1916 //
1917 // Create event to stop the HC when exit boot service.
1918 //
1919 Status = gBS->CreateEventEx (
1920 EVT_NOTIFY_SIGNAL,
1921 TPL_NOTIFY,
1923 Ehc,
1924 &gEfiEventExitBootServicesGuid,
1925 &Ehc->ExitBootServiceEvent
1926 );
1927 if (EFI_ERROR (Status)) {
1928 goto UNINSTALL_USBHC;
1929 }
1930
1931 //
1932 // Install the component name protocol, don't fail the start
1933 // because of something for display.
1934 //
1936 "eng",
1937 gEhciComponentName.SupportedLanguages,
1938 &Ehc->ControllerNameTable,
1939 L"Enhanced Host Controller (USB 2.0)",
1940 TRUE
1941 );
1943 "en",
1944 gEhciComponentName2.SupportedLanguages,
1945 &Ehc->ControllerNameTable,
1946 L"Enhanced Host Controller (USB 2.0)",
1947 FALSE
1948 );
1949
1950 DEBUG ((DEBUG_INFO, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller));
1951 return EFI_SUCCESS;
1952
1953UNINSTALL_USBHC:
1954 gBS->UninstallProtocolInterface (
1955 Controller,
1956 &gEfiUsb2HcProtocolGuid,
1957 &Ehc->Usb2Hc
1958 );
1959
1960FREE_POOL:
1961 EhcFreeSched (Ehc);
1962 gBS->CloseEvent (Ehc->PollTimer);
1963 gBS->FreePool (Ehc);
1964
1965CLOSE_PCIIO:
1966 if (PciAttributesSaved) {
1967 //
1968 // Restore original PCI attributes
1969 //
1970 PciIo->Attributes (
1971 PciIo,
1973 OriginalPciAttributes,
1974 NULL
1975 );
1976 }
1977
1978 gBS->CloseProtocol (
1979 Controller,
1980 &gEfiPciIoProtocolGuid,
1981 This->DriverBindingHandle,
1982 Controller
1983 );
1984
1985 return Status;
1986}
1987
2002EFIAPI
2005 IN EFI_HANDLE Controller,
2006 IN UINTN NumberOfChildren,
2007 IN EFI_HANDLE *ChildHandleBuffer
2008 )
2009{
2010 EFI_STATUS Status;
2011 EFI_USB2_HC_PROTOCOL *Usb2Hc;
2012 EFI_PCI_IO_PROTOCOL *PciIo;
2013 USB2_HC_DEV *Ehc;
2014
2015 //
2016 // Test whether the Controller handler passed in is a valid
2017 // Usb controller handle that should be supported, if not,
2018 // return the error status directly
2019 //
2020 Status = gBS->OpenProtocol (
2021 Controller,
2022 &gEfiUsb2HcProtocolGuid,
2023 (VOID **)&Usb2Hc,
2024 This->DriverBindingHandle,
2025 Controller,
2026 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2027 );
2028
2029 if (EFI_ERROR (Status)) {
2030 return Status;
2031 }
2032
2033 Ehc = EHC_FROM_THIS (Usb2Hc);
2034 PciIo = Ehc->PciIo;
2035
2036 Status = gBS->UninstallProtocolInterface (
2037 Controller,
2038 &gEfiUsb2HcProtocolGuid,
2039 Usb2Hc
2040 );
2041
2042 if (EFI_ERROR (Status)) {
2043 return Status;
2044 }
2045
2046 //
2047 // Stop AsyncRequest Polling timer then stop the EHCI driver
2048 // and uninstall the EHCI protocl.
2049 //
2050 gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL);
2051 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
2052
2053 if (Ehc->PollTimer != NULL) {
2054 gBS->CloseEvent (Ehc->PollTimer);
2055 }
2056
2057 if (Ehc->ExitBootServiceEvent != NULL) {
2058 gBS->CloseEvent (Ehc->ExitBootServiceEvent);
2059 }
2060
2061 EhcFreeSched (Ehc);
2062
2063 if (Ehc->ControllerNameTable != NULL) {
2064 FreeUnicodeStringTable (Ehc->ControllerNameTable);
2065 }
2066
2067 //
2068 // Disable routing of all ports to EHCI controller, so all ports are
2069 // routed back to the UHCI or OHCI controller.
2070 //
2071 EhcClearOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
2072
2073 //
2074 // Restore original PCI attributes
2075 //
2076 PciIo->Attributes (
2077 PciIo,
2079 Ehc->OriginalPciAttributes,
2080 NULL
2081 );
2082
2083 gBS->CloseProtocol (
2084 Controller,
2085 &gEfiPciIoProtocolGuid,
2086 This->DriverBindingHandle,
2087 Controller
2088 );
2089
2090 FreePool (Ehc);
2091
2092 return EFI_SUCCESS;
2093}
UINT64 UINTN
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
EFI_STATUS EFIAPI EhcControlTransfer(IN EFI_USB2_HC_PROTOCOL *This, IN UINT8 DeviceAddress, IN UINT8 DeviceSpeed, IN UINTN MaximumPacketLength, IN EFI_USB_DEVICE_REQUEST *Request, IN EFI_USB_DATA_DIRECTION TransferDirection, IN OUT VOID *Data, IN OUT UINTN *DataLength, IN UINTN TimeOut, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, OUT UINT32 *TransferResult)
Definition: Ehci.c:666
EFI_STATUS EFIAPI EhcGetRootHubPortStatus(IN EFI_USB2_HC_PROTOCOL *This, IN UINT8 PortNumber, OUT EFI_USB_PORT_STATUS *PortStatus)
Definition: Ehci.c:319
EFI_STATUS EFIAPI EhcReset(IN EFI_USB2_HC_PROTOCOL *This, IN UINT16 Attributes)
Definition: Ehci.c:108
VOID EFIAPI EhcExitBootService(EFI_EVENT Event, VOID *Context)
Definition: Ehci.c:1606
EFI_STATUS EFIAPI EhcGetState(IN EFI_USB2_HC_PROTOCOL *This, OUT EFI_USB_HC_STATE *State)
Definition: Ehci.c:202
EFI_STATUS EFIAPI EhcBulkTransfer(IN EFI_USB2_HC_PROTOCOL *This, IN UINT8 DeviceAddress, IN UINT8 EndPointAddress, IN UINT8 DeviceSpeed, IN UINTN MaximumPacketLength, IN UINT8 DataBuffersNumber, IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], IN OUT UINTN *DataLength, IN OUT UINT8 *DataToggle, IN UINTN TimeOut, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, OUT UINT32 *TransferResult)
Definition: Ehci.c:832
EFI_STATUS EFIAPI EhcSyncInterruptTransfer(IN EFI_USB2_HC_PROTOCOL *This, IN UINT8 DeviceAddress, IN UINT8 EndPointAddress, IN UINT8 DeviceSpeed, IN UINTN MaximumPacketLength, IN OUT VOID *Data, IN OUT UINTN *DataLength, IN OUT UINT8 *DataToggle, IN UINTN TimeOut, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, OUT UINT32 *TransferResult)
Definition: Ehci.c:1101
EFI_STATUS EFIAPI EhcDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
Definition: Ehci.c:1326
EFI_STATUS EFIAPI EhcDriverEntryPoint(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: Ehci.c:1296
USB2_HC_DEV * EhcCreateUsb2Hc(IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN UINT64 OriginalPciAttributes)
Definition: Ehci.c:1520
EFI_STATUS EFIAPI EhcDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer)
Definition: Ehci.c:2003
EFI_STATUS EFIAPI EhcSetState(IN EFI_USB2_HC_PROTOCOL *This, IN EFI_USB_HC_STATE State)
Definition: Ehci.c:243
EFI_STATUS EhcGetUsbDebugPortInfo(IN USB2_HC_DEV *Ehc)
Definition: Ehci.c:1395
EFI_STATUS EFIAPI EhcIsochronousTransfer(IN EFI_USB2_HC_PROTOCOL *This, IN UINT8 DeviceAddress, IN UINT8 EndPointAddress, IN UINT8 DeviceSpeed, IN UINTN MaximumPacketLength, IN UINT8 DataBuffersNumber, IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], IN UINTN DataLength, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, OUT UINT32 *TransferResult)
Definition: Ehci.c:1226
EFI_STATUS EFIAPI EhcGetCapability(IN EFI_USB2_HC_PROTOCOL *This, OUT UINT8 *MaxSpeed, OUT UINT8 *PortNumber, OUT UINT8 *Is64BitCapable)
Definition: Ehci.c:66
EFI_STATUS EFIAPI EhcDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
Definition: Ehci.c:1637
EFI_STATUS EFIAPI EhcAsyncIsochronousTransfer(IN EFI_USB2_HC_PROTOCOL *This, IN UINT8 DeviceAddress, IN UINT8 EndPointAddress, IN UINT8 DeviceSpeed, IN UINTN MaximumPacketLength, IN UINT8 DataBuffersNumber, IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], IN UINTN DataLength, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, IN VOID *Context)
Definition: Ehci.c:1267
EFI_STATUS EFIAPI EhcAsyncInterruptTransfer(IN EFI_USB2_HC_PROTOCOL *This, IN UINT8 DeviceAddress, IN UINT8 EndPointAddress, IN UINT8 DeviceSpeed, IN UINTN MaximumPacketLength, IN BOOLEAN IsNewTransfer, IN OUT UINT8 *DataToggle, IN UINTN PollingInterval, IN UINTN DataLength, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, IN VOID *Context OPTIONAL)
Definition: Ehci.c:979
EFI_STATUS EFIAPI EhcSetRootHubPortFeature(IN EFI_USB2_HC_PROTOCOL *This, IN UINT8 PortNumber, IN EFI_USB_PORT_FEATURE PortFeature)
Definition: Ehci.c:410
EFI_STATUS EFIAPI EhcClearRootHubPortFeature(IN EFI_USB2_HC_PROTOCOL *This, IN UINT8 PortNumber, IN EFI_USB_PORT_FEATURE PortFeature)
Definition: Ehci.c:523
URB * EhciInsertAsyncIntTransfer(IN USB2_HC_DEV *Ehc, IN UINT8 DevAddr, IN UINT8 EpAddr, IN UINT8 DevSpeed, IN UINT8 Toggle, IN UINTN MaxPacket, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Hub, IN UINTN DataLen, IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, IN VOID *Context, IN UINTN Interval)
Definition: EhciSched.c:819
EFI_STATUS EhciDelAsyncIntTransfer(IN USB2_HC_DEV *Ehc, IN UINT8 DevAddr, IN UINT8 EpNum, OUT UINT8 *DataToggle)
Definition: EhciSched.c:733
VOID EhcLinkQhToAsync(IN USB2_HC_DEV *Ehc, IN EHC_QH *Qh)
Definition: EhciSched.c:312
VOID EhcFreeSched(IN USB2_HC_DEV *Ehc)
Definition: EhciSched.c:250
VOID EFIAPI EhcMonitorAsyncRequests(IN EFI_EVENT Event, IN VOID *Context)
Definition: EhciSched.c:1021
EFI_STATUS EhcExecTransfer(IN USB2_HC_DEV *Ehc, IN URB *Urb, IN UINTN TimeOut)
Definition: EhciSched.c:668
VOID EhcUnlinkQhFromPeriod(IN USB2_HC_DEV *Ehc, IN EHC_QH *Qh)
Definition: EhciSched.c:490
VOID EhciDelAllAsyncIntTransfers(IN USB2_HC_DEV *Ehc)
Definition: EhciSched.c:780
VOID EhcLinkQhToPeriod(IN USB2_HC_DEV *Ehc, IN EHC_QH *Qh)
Definition: EhciSched.c:389
VOID EhcUnlinkQhFromAsync(IN USB2_HC_DEV *Ehc, IN EHC_QH *Qh)
Definition: EhciSched.c:345
URB * EhcCreateUrb(IN USB2_HC_DEV *Ehc, IN UINT8 DevAddr, IN UINT8 EpAddr, IN UINT8 DevSpeed, IN UINT8 Toggle, IN UINTN MaxPacket, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Hub, IN UINTN Type, IN EFI_USB_DEVICE_REQUEST *Request, IN VOID *Data, IN UINTN DataLen, IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, IN VOID *Context, IN UINTN Interval)
Definition: EhciUrb.c:528
VOID EhcFreeUrb(IN USB2_HC_DEV *Ehc, IN URB *Urb)
Definition: EhciUrb.c:313
VOID EhcClearOpRegBit(IN USB2_HC_DEV *Ehc, IN UINT32 Offset, IN UINT32 Bit)
Definition: EhciReg.c:238
EFI_STATUS EhcResetHC(IN USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhciReg.c:477
VOID EhcWriteOpReg(IN USB2_HC_DEV *Ehc, IN UINT32 Offset, IN UINT32 Data)
Definition: EhciReg.c:183
EFI_STATUS EhcInitHC(IN USB2_HC_DEV *Ehc)
Definition: EhciReg.c:562
BOOLEAN EhcIsHalt(IN USB2_HC_DEV *Ehc)
Definition: EhciReg.c:442
EFI_STATUS EhcHaltHC(IN USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhciReg.c:511
VOID EhcClearLegacySupport(IN USB2_HC_DEV *Ehc)
Definition: EhciReg.c:295
UINT32 EhcReadCapRegister(IN USB2_HC_DEV *Ehc, IN UINT32 Offset)
Definition: EhciReg.c:23
BOOLEAN EhcIsSysError(IN USB2_HC_DEV *Ehc)
Definition: EhciReg.c:459
EFI_STATUS EhcRunHC(IN USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhciReg.c:534
UINT32 EhcReadOpReg(IN USB2_HC_DEV *Ehc, IN UINT32 Offset)
Definition: EhciReg.c:147
VOID EhcAckAllInterrupt(IN USB2_HC_DEV *Ehc)
Definition: EhciReg.c:376
BOOLEAN EhcIsDebugPortInUse(IN CONST USB2_HC_DEV *Ehc, IN CONST UINT8 *PortNumber OPTIONAL)
Definition: EhciReg.c:104
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define REPORT_STATUS_CODE_WITH_DEVICE_PATH(Type, Value, DevicePathParameter)
#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
Clear for PCI controllers that can not genrate a DAC.
Definition: PciIo.h:64
@ EfiPciIoAttributeOperationGet
Definition: PciIo.h:103
@ EfiPciIoAttributeOperationEnable
Definition: PciIo.h:111
@ EfiPciIoAttributeOperationSet
Definition: PciIo.h:107
@ EfiPciIoAttributeOperationSupported
Definition: PciIo.h:119
EFI_USB_PORT_FEATURE
#define USB_PORT_STAT_C_CONNECTION
EFI_USB_HC_STATE
@ EfiUsbHcStateHalt
@ EfiUsbHcStateOperational
@ EfiUsbHcStateSuspend
#define USB_PORT_STAT_CONNECTION
EFI_USB_DATA_DIRECTION
Definition: UsbIo.h:44
EFI_STATUS(EFIAPI * EFI_ASYNC_USB_TRANSFER_CALLBACK)(IN VOID *Data, IN UINTN DataLength, IN VOID *Context, IN UINT32 Status)
Definition: UsbIo.h:80
#define FeaturePcdGet(TokenName)
Definition: PcdLib.h:50
#define EFI_PCI_STATUS_CAPABILITY
0x0010
Definition: Pci22.h:629
#define PCI_IF_EHCI
Definition: Pci23.h:53
#define EFI_PROGRESS_CODE
Definition: PiStatusCode.h:43
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINTN EFI_TPL
Definition: UefiBaseType.h:41
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI AddUnicodeString2(IN CONST CHAR8 *Language, IN CONST CHAR8 *SupportedLanguages, IN OUT EFI_UNICODE_STRING_TABLE **UnicodeStringTable, IN CONST CHAR16 *UnicodeString, IN BOOLEAN Iso639Language)
Definition: UefiLib.c:1087
EFI_STATUS EFIAPI EfiLibInstallDriverBindingComponentName2(IN CONST EFI_HANDLE ImageHandle, IN CONST EFI_SYSTEM_TABLE *SystemTable, IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, IN EFI_HANDLE DriverBindingHandle, IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName OPTIONAL, IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL)
EFI_STATUS EFIAPI FreeUnicodeStringTable(IN EFI_UNICODE_STRING_TABLE *UnicodeStringTable)
Definition: UefiLib.c:1257
@ EFI_NATIVE_INTERFACE
Definition: UefiSpec.h:1193
@ TimerCancel
Definition: UefiSpec.h:531
@ TimerPeriodic
Definition: UefiSpec.h:535
@ ByProtocol
Definition: UefiSpec.h:1518
Definition: EhciUrb.h:200
EFI_PCI_IO_PROTOCOL_CONFIG Read
Definition: PciIo.h:232