]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
MdeModulePkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / EhciDxe / Ehci.c
1 /** @file
2 The Ehci controller driver.
3
4 EhciDxe driver is responsible for managing the behavior of EHCI controller.
5 It implements the interfaces of monitoring the status of all ports and transferring
6 Control, Bulk, Interrupt and Isochronous requests to Usb2.0 device.
7
8 Note that EhciDxe driver is enhanced to guarantee that the EHCI controller get attached
9 to the EHCI controller before a UHCI or OHCI driver attaches to the companion UHCI or
10 OHCI controller. This way avoids the control transfer on a shared port between EHCI
11 and companion host controller when UHCI or OHCI gets attached earlier than EHCI and a
12 USB 2.0 device inserts.
13
14 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
15 SPDX-License-Identifier: BSD-2-Clause-Patent
16
17 **/
18
19
20 #include "Ehci.h"
21
22 //
23 // Two arrays used to translate the EHCI port state (change)
24 // to the UEFI protocol's port state (change).
25 //
26 USB_PORT_STATE_MAP mUsbPortStateMap[] = {
27 {PORTSC_CONN, USB_PORT_STAT_CONNECTION},
28 {PORTSC_ENABLED, USB_PORT_STAT_ENABLE},
29 {PORTSC_SUSPEND, USB_PORT_STAT_SUSPEND},
30 {PORTSC_OVERCUR, USB_PORT_STAT_OVERCURRENT},
31 {PORTSC_RESET, USB_PORT_STAT_RESET},
32 {PORTSC_POWER, USB_PORT_STAT_POWER},
33 {PORTSC_OWNER, USB_PORT_STAT_OWNER}
34 };
35
36 USB_PORT_STATE_MAP mUsbPortChangeMap[] = {
37 {PORTSC_CONN_CHANGE, USB_PORT_STAT_C_CONNECTION},
38 {PORTSC_ENABLE_CHANGE, USB_PORT_STAT_C_ENABLE},
39 {PORTSC_OVERCUR_CHANGE, USB_PORT_STAT_C_OVERCURRENT}
40 };
41
42 EFI_DRIVER_BINDING_PROTOCOL
43 gEhciDriverBinding = {
44 EhcDriverBindingSupported,
45 EhcDriverBindingStart,
46 EhcDriverBindingStop,
47 0x30,
48 NULL,
49 NULL
50 };
51
52 /**
53 Retrieves the capability of root hub ports.
54
55 @param This This EFI_USB_HC_PROTOCOL instance.
56 @param MaxSpeed Max speed supported by the controller.
57 @param PortNumber Number of the root hub ports.
58 @param Is64BitCapable Whether the controller supports 64-bit memory
59 addressing.
60
61 @retval EFI_SUCCESS Host controller capability were retrieved successfully.
62 @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.
63
64 **/
65 EFI_STATUS
66 EFIAPI
67 EhcGetCapability (
68 IN EFI_USB2_HC_PROTOCOL *This,
69 OUT UINT8 *MaxSpeed,
70 OUT UINT8 *PortNumber,
71 OUT UINT8 *Is64BitCapable
72 )
73 {
74 USB2_HC_DEV *Ehc;
75 EFI_TPL OldTpl;
76
77 if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {
78 return EFI_INVALID_PARAMETER;
79 }
80
81 OldTpl = gBS->RaiseTPL (EHC_TPL);
82 Ehc = EHC_FROM_THIS (This);
83
84 *MaxSpeed = EFI_USB_SPEED_HIGH;
85 *PortNumber = (UINT8) (Ehc->HcStructParams & HCSP_NPORTS);
86 *Is64BitCapable = (UINT8) Ehc->Support64BitDma;
87
88 DEBUG ((DEBUG_INFO, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));
89
90 gBS->RestoreTPL (OldTpl);
91 return EFI_SUCCESS;
92 }
93
94
95 /**
96 Provides software reset for the USB host controller.
97
98 @param This This EFI_USB2_HC_PROTOCOL instance.
99 @param Attributes A bit mask of the reset operation to perform.
100
101 @retval EFI_SUCCESS The reset operation succeeded.
102 @retval EFI_INVALID_PARAMETER Attributes is not valid.
103 @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
104 not currently supported by the host controller.
105 @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
106
107 **/
108 EFI_STATUS
109 EFIAPI
110 EhcReset (
111 IN EFI_USB2_HC_PROTOCOL *This,
112 IN UINT16 Attributes
113 )
114 {
115 USB2_HC_DEV *Ehc;
116 EFI_TPL OldTpl;
117 EFI_STATUS Status;
118
119 Ehc = EHC_FROM_THIS (This);
120
121 if (Ehc->DevicePath != NULL) {
122 //
123 // Report Status Code to indicate reset happens
124 //
125 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
126 EFI_PROGRESS_CODE,
127 (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),
128 Ehc->DevicePath
129 );
130 }
131
132 OldTpl = gBS->RaiseTPL (EHC_TPL);
133
134 switch (Attributes) {
135 case EFI_USB_HC_RESET_GLOBAL:
136 //
137 // Flow through, same behavior as Host Controller Reset
138 //
139 case EFI_USB_HC_RESET_HOST_CONTROLLER:
140 //
141 // Host Controller must be Halt when Reset it
142 //
143 if (EhcIsDebugPortInUse (Ehc, NULL)) {
144 Status = EFI_SUCCESS;
145 goto ON_EXIT;
146 }
147
148 if (!EhcIsHalt (Ehc)) {
149 Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
150
151 if (EFI_ERROR (Status)) {
152 Status = EFI_DEVICE_ERROR;
153 goto ON_EXIT;
154 }
155 }
156
157 //
158 // Clean up the asynchronous transfers, currently only
159 // interrupt supports asynchronous operation.
160 //
161 EhciDelAllAsyncIntTransfers (Ehc);
162 EhcAckAllInterrupt (Ehc);
163 EhcFreeSched (Ehc);
164
165 Status = EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
166
167 if (EFI_ERROR (Status)) {
168 goto ON_EXIT;
169 }
170
171 Status = EhcInitHC (Ehc);
172 break;
173
174 case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:
175 case EFI_USB_HC_RESET_HOST_WITH_DEBUG:
176 Status = EFI_UNSUPPORTED;
177 break;
178
179 default:
180 Status = EFI_INVALID_PARAMETER;
181 }
182
183 ON_EXIT:
184 DEBUG ((DEBUG_INFO, "EhcReset: exit status %r\n", Status));
185 gBS->RestoreTPL (OldTpl);
186 return Status;
187 }
188
189
190 /**
191 Retrieve the current state of the USB host controller.
192
193 @param This This EFI_USB2_HC_PROTOCOL instance.
194 @param State Variable to return the current host controller
195 state.
196
197 @retval EFI_SUCCESS Host controller state was returned in State.
198 @retval EFI_INVALID_PARAMETER State is NULL.
199 @retval EFI_DEVICE_ERROR An error was encountered while attempting to
200 retrieve the host controller's current state.
201
202 **/
203 EFI_STATUS
204 EFIAPI
205 EhcGetState (
206 IN EFI_USB2_HC_PROTOCOL *This,
207 OUT EFI_USB_HC_STATE *State
208 )
209 {
210 EFI_TPL OldTpl;
211 USB2_HC_DEV *Ehc;
212
213 if (State == NULL) {
214 return EFI_INVALID_PARAMETER;
215 }
216
217 OldTpl = gBS->RaiseTPL (EHC_TPL);
218 Ehc = EHC_FROM_THIS (This);
219
220 if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
221 *State = EfiUsbHcStateHalt;
222 } else {
223 *State = EfiUsbHcStateOperational;
224 }
225
226 gBS->RestoreTPL (OldTpl);
227
228 DEBUG ((DEBUG_INFO, "EhcGetState: current state %d\n", *State));
229 return EFI_SUCCESS;
230 }
231
232
233 /**
234 Sets the USB host controller to a specific state.
235
236 @param This This EFI_USB2_HC_PROTOCOL instance.
237 @param State The state of the host controller that will be set.
238
239 @retval EFI_SUCCESS The USB host controller was successfully placed
240 in the state specified by State.
241 @retval EFI_INVALID_PARAMETER State is invalid.
242 @retval EFI_DEVICE_ERROR Failed to set the state due to device error.
243
244 **/
245 EFI_STATUS
246 EFIAPI
247 EhcSetState (
248 IN EFI_USB2_HC_PROTOCOL *This,
249 IN EFI_USB_HC_STATE State
250 )
251 {
252 USB2_HC_DEV *Ehc;
253 EFI_TPL OldTpl;
254 EFI_STATUS Status;
255 EFI_USB_HC_STATE CurState;
256
257 Status = EhcGetState (This, &CurState);
258
259 if (EFI_ERROR (Status)) {
260 return EFI_DEVICE_ERROR;
261 }
262
263 if (CurState == State) {
264 return EFI_SUCCESS;
265 }
266
267 OldTpl = gBS->RaiseTPL (EHC_TPL);
268 Ehc = EHC_FROM_THIS (This);
269
270 switch (State) {
271 case EfiUsbHcStateHalt:
272 Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
273 break;
274
275 case EfiUsbHcStateOperational:
276 if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR)) {
277 Status = EFI_DEVICE_ERROR;
278 break;
279 }
280
281 //
282 // Software must not write a one to this field unless the host controller
283 // is in the Halted state. Doing so will yield undefined results.
284 // refers to Spec[EHCI1.0-2.3.1]
285 //
286 if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
287 Status = EFI_DEVICE_ERROR;
288 break;
289 }
290
291 Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
292 break;
293
294 case EfiUsbHcStateSuspend:
295 Status = EFI_UNSUPPORTED;
296 break;
297
298 default:
299 Status = EFI_INVALID_PARAMETER;
300 }
301
302 DEBUG ((DEBUG_INFO, "EhcSetState: exit status %r\n", Status));
303 gBS->RestoreTPL (OldTpl);
304 return Status;
305 }
306
307
308 /**
309 Retrieves the current status of a USB root hub port.
310
311 @param This This EFI_USB2_HC_PROTOCOL instance.
312 @param PortNumber The root hub port to retrieve the state from.
313 This value is zero-based.
314 @param PortStatus Variable to receive the port state.
315
316 @retval EFI_SUCCESS The status of the USB root hub port specified.
317 by PortNumber was returned in PortStatus.
318 @retval EFI_INVALID_PARAMETER PortNumber is invalid.
319 @retval EFI_DEVICE_ERROR Can't read register.
320
321 **/
322 EFI_STATUS
323 EFIAPI
324 EhcGetRootHubPortStatus (
325 IN EFI_USB2_HC_PROTOCOL *This,
326 IN UINT8 PortNumber,
327 OUT EFI_USB_PORT_STATUS *PortStatus
328 )
329 {
330 USB2_HC_DEV *Ehc;
331 EFI_TPL OldTpl;
332 UINT32 Offset;
333 UINT32 State;
334 UINT32 TotalPort;
335 UINTN Index;
336 UINTN MapSize;
337 EFI_STATUS Status;
338
339 if (PortStatus == NULL) {
340 return EFI_INVALID_PARAMETER;
341 }
342
343 OldTpl = gBS->RaiseTPL (EHC_TPL);
344
345 Ehc = EHC_FROM_THIS (This);
346 Status = EFI_SUCCESS;
347
348 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
349
350 if (PortNumber >= TotalPort) {
351 Status = EFI_INVALID_PARAMETER;
352 goto ON_EXIT;
353 }
354
355 Offset = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
356 PortStatus->PortStatus = 0;
357 PortStatus->PortChangeStatus = 0;
358
359 if (EhcIsDebugPortInUse (Ehc, &PortNumber)) {
360 goto ON_EXIT;
361 }
362
363 State = EhcReadOpReg (Ehc, Offset);
364
365 //
366 // Identify device speed. If in K state, it is low speed.
367 // If the port is enabled after reset, the device is of
368 // high speed. The USB bus driver should retrieve the actual
369 // port speed after reset.
370 //
371 if (EHC_BIT_IS_SET (State, PORTSC_LINESTATE_K)) {
372 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
373
374 } else if (EHC_BIT_IS_SET (State, PORTSC_ENABLED)) {
375 PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
376 }
377
378 //
379 // Convert the EHCI port/port change state to UEFI status
380 //
381 MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
382
383 for (Index = 0; Index < MapSize; Index++) {
384 if (EHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
385 PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
386 }
387 }
388
389 MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
390
391 for (Index = 0; Index < MapSize; Index++) {
392 if (EHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
393 PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
394 }
395 }
396
397 ON_EXIT:
398 gBS->RestoreTPL (OldTpl);
399 return Status;
400 }
401
402
403 /**
404 Sets a feature for the specified root hub port.
405
406 @param This This EFI_USB2_HC_PROTOCOL instance.
407 @param PortNumber Root hub port to set.
408 @param PortFeature Feature to set.
409
410 @retval EFI_SUCCESS The feature specified by PortFeature was set.
411 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
412 @retval EFI_DEVICE_ERROR Can't read register.
413
414 **/
415 EFI_STATUS
416 EFIAPI
417 EhcSetRootHubPortFeature (
418 IN EFI_USB2_HC_PROTOCOL *This,
419 IN UINT8 PortNumber,
420 IN EFI_USB_PORT_FEATURE PortFeature
421 )
422 {
423 USB2_HC_DEV *Ehc;
424 EFI_TPL OldTpl;
425 UINT32 Offset;
426 UINT32 State;
427 UINT32 TotalPort;
428 EFI_STATUS Status;
429
430 OldTpl = gBS->RaiseTPL (EHC_TPL);
431 Ehc = EHC_FROM_THIS (This);
432 Status = EFI_SUCCESS;
433
434 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
435
436 if (PortNumber >= TotalPort) {
437 Status = EFI_INVALID_PARAMETER;
438 goto ON_EXIT;
439 }
440
441 Offset = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
442 State = EhcReadOpReg (Ehc, Offset);
443
444 //
445 // Mask off the port status change bits, these bits are
446 // write clean bit
447 //
448 State &= ~PORTSC_CHANGE_MASK;
449
450 switch (PortFeature) {
451 case EfiUsbPortEnable:
452 //
453 // Sofeware can't set this bit, Port can only be enable by
454 // EHCI as a part of the reset and enable
455 //
456 State |= PORTSC_ENABLED;
457 EhcWriteOpReg (Ehc, Offset, State);
458 break;
459
460 case EfiUsbPortSuspend:
461 State |= PORTSC_SUSPEND;
462 EhcWriteOpReg (Ehc, Offset, State);
463 break;
464
465 case EfiUsbPortReset:
466 //
467 // Make sure Host Controller not halt before reset it
468 //
469 if (EhcIsHalt (Ehc)) {
470 Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
471
472 if (EFI_ERROR (Status)) {
473 DEBUG ((DEBUG_INFO, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status));
474 break;
475 }
476 }
477
478 //
479 // Set one to PortReset bit must also set zero to PortEnable bit
480 //
481 State |= PORTSC_RESET;
482 State &= ~PORTSC_ENABLED;
483 EhcWriteOpReg (Ehc, Offset, State);
484 break;
485
486 case EfiUsbPortPower:
487 //
488 // Set port power bit when PPC is 1
489 //
490 if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) {
491 State |= PORTSC_POWER;
492 EhcWriteOpReg (Ehc, Offset, State);
493 }
494 break;
495
496 case EfiUsbPortOwner:
497 State |= PORTSC_OWNER;
498 EhcWriteOpReg (Ehc, Offset, State);
499 break;
500
501 default:
502 Status = EFI_INVALID_PARAMETER;
503 }
504
505 ON_EXIT:
506 DEBUG ((DEBUG_INFO, "EhcSetRootHubPortFeature: exit status %r\n", Status));
507
508 gBS->RestoreTPL (OldTpl);
509 return Status;
510 }
511
512
513 /**
514 Clears a feature for the specified root hub port.
515
516 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
517 @param PortNumber Specifies the root hub port whose feature is
518 requested to be cleared.
519 @param PortFeature Indicates the feature selector associated with the
520 feature clear request.
521
522 @retval EFI_SUCCESS The feature specified by PortFeature was cleared
523 for the USB root hub port specified by PortNumber.
524 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
525 @retval EFI_DEVICE_ERROR Can't read register.
526
527 **/
528 EFI_STATUS
529 EFIAPI
530 EhcClearRootHubPortFeature (
531 IN EFI_USB2_HC_PROTOCOL *This,
532 IN UINT8 PortNumber,
533 IN EFI_USB_PORT_FEATURE PortFeature
534 )
535 {
536 USB2_HC_DEV *Ehc;
537 EFI_TPL OldTpl;
538 UINT32 Offset;
539 UINT32 State;
540 UINT32 TotalPort;
541 EFI_STATUS Status;
542
543 OldTpl = gBS->RaiseTPL (EHC_TPL);
544 Ehc = EHC_FROM_THIS (This);
545 Status = EFI_SUCCESS;
546
547 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
548
549 if (PortNumber >= TotalPort) {
550 Status = EFI_INVALID_PARAMETER;
551 goto ON_EXIT;
552 }
553
554 Offset = EHC_PORT_STAT_OFFSET + (4 * PortNumber);
555 State = EhcReadOpReg (Ehc, Offset);
556 State &= ~PORTSC_CHANGE_MASK;
557
558 switch (PortFeature) {
559 case EfiUsbPortEnable:
560 //
561 // Clear PORT_ENABLE feature means disable port.
562 //
563 State &= ~PORTSC_ENABLED;
564 EhcWriteOpReg (Ehc, Offset, State);
565 break;
566
567 case EfiUsbPortSuspend:
568 //
569 // A write of zero to this bit is ignored by the host
570 // controller. The host controller will unconditionally
571 // set this bit to a zero when:
572 // 1. software sets the Forct Port Resume bit to a zero from a one.
573 // 2. software sets the Port Reset bit to a one frome a zero.
574 //
575 State &= ~PORSTSC_RESUME;
576 EhcWriteOpReg (Ehc, Offset, State);
577 break;
578
579 case EfiUsbPortReset:
580 //
581 // Clear PORT_RESET means clear the reset signal.
582 //
583 State &= ~PORTSC_RESET;
584 EhcWriteOpReg (Ehc, Offset, State);
585 break;
586
587 case EfiUsbPortOwner:
588 //
589 // Clear port owner means this port owned by EHC
590 //
591 State &= ~PORTSC_OWNER;
592 EhcWriteOpReg (Ehc, Offset, State);
593 break;
594
595 case EfiUsbPortConnectChange:
596 //
597 // Clear connect status change
598 //
599 State |= PORTSC_CONN_CHANGE;
600 EhcWriteOpReg (Ehc, Offset, State);
601 break;
602
603 case EfiUsbPortEnableChange:
604 //
605 // Clear enable status change
606 //
607 State |= PORTSC_ENABLE_CHANGE;
608 EhcWriteOpReg (Ehc, Offset, State);
609 break;
610
611 case EfiUsbPortOverCurrentChange:
612 //
613 // Clear PortOverCurrent change
614 //
615 State |= PORTSC_OVERCUR_CHANGE;
616 EhcWriteOpReg (Ehc, Offset, State);
617 break;
618
619 case EfiUsbPortPower:
620 //
621 // Clear port power bit when PPC is 1
622 //
623 if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) {
624 State &= ~PORTSC_POWER;
625 EhcWriteOpReg (Ehc, Offset, State);
626 }
627 break;
628 case EfiUsbPortSuspendChange:
629 case EfiUsbPortResetChange:
630 //
631 // Not supported or not related operation
632 //
633 break;
634
635 default:
636 Status = EFI_INVALID_PARAMETER;
637 break;
638 }
639
640 ON_EXIT:
641 DEBUG ((DEBUG_INFO, "EhcClearRootHubPortFeature: exit status %r\n", Status));
642 gBS->RestoreTPL (OldTpl);
643 return Status;
644 }
645
646
647 /**
648 Submits control transfer to a target USB device.
649
650 @param This This EFI_USB2_HC_PROTOCOL instance.
651 @param DeviceAddress The target device address.
652 @param DeviceSpeed Target device speed.
653 @param MaximumPacketLength Maximum packet size the default control transfer
654 endpoint is capable of sending or receiving.
655 @param Request USB device request to send.
656 @param TransferDirection Specifies the data direction for the data stage
657 @param Data Data buffer to be transmitted or received from USB
658 device.
659 @param DataLength The size (in bytes) of the data buffer.
660 @param TimeOut Indicates the maximum timeout, in millisecond.
661 @param Translator Transaction translator to be used by this device.
662 @param TransferResult Return the result of this control transfer.
663
664 @retval EFI_SUCCESS Transfer was completed successfully.
665 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
666 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
667 @retval EFI_TIMEOUT Transfer failed due to timeout.
668 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
669
670 **/
671 EFI_STATUS
672 EFIAPI
673 EhcControlTransfer (
674 IN EFI_USB2_HC_PROTOCOL *This,
675 IN UINT8 DeviceAddress,
676 IN UINT8 DeviceSpeed,
677 IN UINTN MaximumPacketLength,
678 IN EFI_USB_DEVICE_REQUEST *Request,
679 IN EFI_USB_DATA_DIRECTION TransferDirection,
680 IN OUT VOID *Data,
681 IN OUT UINTN *DataLength,
682 IN UINTN TimeOut,
683 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
684 OUT UINT32 *TransferResult
685 )
686 {
687 USB2_HC_DEV *Ehc;
688 URB *Urb;
689 EFI_TPL OldTpl;
690 UINT8 Endpoint;
691 EFI_STATUS Status;
692
693 //
694 // Validate parameters
695 //
696 if ((Request == NULL) || (TransferResult == NULL)) {
697 return EFI_INVALID_PARAMETER;
698 }
699
700 if ((TransferDirection != EfiUsbDataIn) &&
701 (TransferDirection != EfiUsbDataOut) &&
702 (TransferDirection != EfiUsbNoData)) {
703 return EFI_INVALID_PARAMETER;
704 }
705
706 if ((TransferDirection == EfiUsbNoData) &&
707 ((Data != NULL) || (*DataLength != 0))) {
708 return EFI_INVALID_PARAMETER;
709 }
710
711 if ((TransferDirection != EfiUsbNoData) &&
712 ((Data == NULL) || (*DataLength == 0))) {
713 return EFI_INVALID_PARAMETER;
714 }
715
716 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&
717 (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {
718 return EFI_INVALID_PARAMETER;
719 }
720
721 if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {
722 return EFI_INVALID_PARAMETER;
723 }
724
725 OldTpl = gBS->RaiseTPL (EHC_TPL);
726 Ehc = EHC_FROM_THIS (This);
727
728 Status = EFI_DEVICE_ERROR;
729 *TransferResult = EFI_USB_ERR_SYSTEM;
730
731 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
732 DEBUG ((DEBUG_ERROR, "EhcControlTransfer: HC halted at entrance\n"));
733
734 EhcAckAllInterrupt (Ehc);
735 goto ON_EXIT;
736 }
737
738 EhcAckAllInterrupt (Ehc);
739
740 //
741 // Create a new URB, insert it into the asynchronous
742 // schedule list, then poll the execution status.
743 //
744 //
745 // Encode the direction in address, although default control
746 // endpoint is bidirectional. EhcCreateUrb expects this
747 // combination of Ep addr and its direction.
748 //
749 Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
750 Urb = EhcCreateUrb (
751 Ehc,
752 DeviceAddress,
753 Endpoint,
754 DeviceSpeed,
755 0,
756 MaximumPacketLength,
757 Translator,
758 EHC_CTRL_TRANSFER,
759 Request,
760 Data,
761 *DataLength,
762 NULL,
763 NULL,
764 1
765 );
766
767 if (Urb == NULL) {
768 DEBUG ((DEBUG_ERROR, "EhcControlTransfer: failed to create URB"));
769
770 Status = EFI_OUT_OF_RESOURCES;
771 goto ON_EXIT;
772 }
773
774 EhcLinkQhToAsync (Ehc, Urb->Qh);
775 Status = EhcExecTransfer (Ehc, Urb, TimeOut);
776 EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
777
778 //
779 // Get the status from URB. The result is updated in EhcCheckUrbResult
780 // which is called by EhcExecTransfer
781 //
782 *TransferResult = Urb->Result;
783 *DataLength = Urb->Completed;
784
785 if (*TransferResult == EFI_USB_NOERROR) {
786 Status = EFI_SUCCESS;
787 }
788
789 EhcAckAllInterrupt (Ehc);
790 EhcFreeUrb (Ehc, Urb);
791
792 ON_EXIT:
793 Ehc->PciIo->Flush (Ehc->PciIo);
794 gBS->RestoreTPL (OldTpl);
795
796 if (EFI_ERROR (Status)) {
797 DEBUG ((DEBUG_ERROR, "EhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
798 }
799
800 return Status;
801 }
802
803
804 /**
805 Submits bulk transfer to a bulk endpoint of a USB device.
806
807 @param This This EFI_USB2_HC_PROTOCOL instance.
808 @param DeviceAddress Target device address.
809 @param EndPointAddress Endpoint number and its direction in bit 7.
810 @param DeviceSpeed Device speed, Low speed device doesn't support bulk
811 transfer.
812 @param MaximumPacketLength Maximum packet size the endpoint is capable of
813 sending or receiving.
814 @param DataBuffersNumber Number of data buffers prepared for the transfer.
815 @param Data Array of pointers to the buffers of data to transmit
816 from or receive into.
817 @param DataLength The lenght of the data buffer.
818 @param DataToggle On input, the initial data toggle for the transfer;
819 On output, it is updated to to next data toggle to
820 use of the subsequent bulk transfer.
821 @param TimeOut Indicates the maximum time, in millisecond, which
822 the transfer is allowed to complete.
823 @param Translator A pointr to the transaction translator data.
824 @param TransferResult A pointer to the detailed result information of the
825 bulk transfer.
826
827 @retval EFI_SUCCESS The transfer was completed successfully.
828 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
829 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
830 @retval EFI_TIMEOUT The transfer failed due to timeout.
831 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
832
833 **/
834 EFI_STATUS
835 EFIAPI
836 EhcBulkTransfer (
837 IN EFI_USB2_HC_PROTOCOL *This,
838 IN UINT8 DeviceAddress,
839 IN UINT8 EndPointAddress,
840 IN UINT8 DeviceSpeed,
841 IN UINTN MaximumPacketLength,
842 IN UINT8 DataBuffersNumber,
843 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
844 IN OUT UINTN *DataLength,
845 IN OUT UINT8 *DataToggle,
846 IN UINTN TimeOut,
847 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
848 OUT UINT32 *TransferResult
849 )
850 {
851 USB2_HC_DEV *Ehc;
852 URB *Urb;
853 EFI_TPL OldTpl;
854 EFI_STATUS Status;
855
856 //
857 // Validate the parameters
858 //
859 if ((DataLength == NULL) || (*DataLength == 0) ||
860 (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {
861 return EFI_INVALID_PARAMETER;
862 }
863
864 if ((*DataToggle != 0) && (*DataToggle != 1)) {
865 return EFI_INVALID_PARAMETER;
866 }
867
868 if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
869 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
870 ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) {
871 return EFI_INVALID_PARAMETER;
872 }
873
874 OldTpl = gBS->RaiseTPL (EHC_TPL);
875 Ehc = EHC_FROM_THIS (This);
876
877 *TransferResult = EFI_USB_ERR_SYSTEM;
878 Status = EFI_DEVICE_ERROR;
879
880 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
881 DEBUG ((DEBUG_ERROR, "EhcBulkTransfer: HC is halted\n"));
882
883 EhcAckAllInterrupt (Ehc);
884 goto ON_EXIT;
885 }
886
887 EhcAckAllInterrupt (Ehc);
888
889 //
890 // Create a new URB, insert it into the asynchronous
891 // schedule list, then poll the execution status.
892 //
893 Urb = EhcCreateUrb (
894 Ehc,
895 DeviceAddress,
896 EndPointAddress,
897 DeviceSpeed,
898 *DataToggle,
899 MaximumPacketLength,
900 Translator,
901 EHC_BULK_TRANSFER,
902 NULL,
903 Data[0],
904 *DataLength,
905 NULL,
906 NULL,
907 1
908 );
909
910 if (Urb == NULL) {
911 DEBUG ((DEBUG_ERROR, "EhcBulkTransfer: failed to create URB\n"));
912
913 Status = EFI_OUT_OF_RESOURCES;
914 goto ON_EXIT;
915 }
916
917 EhcLinkQhToAsync (Ehc, Urb->Qh);
918 Status = EhcExecTransfer (Ehc, Urb, TimeOut);
919 EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
920
921 *TransferResult = Urb->Result;
922 *DataLength = Urb->Completed;
923 *DataToggle = Urb->DataToggle;
924
925 if (*TransferResult == EFI_USB_NOERROR) {
926 Status = EFI_SUCCESS;
927 }
928
929 EhcAckAllInterrupt (Ehc);
930 EhcFreeUrb (Ehc, Urb);
931
932 ON_EXIT:
933 Ehc->PciIo->Flush (Ehc->PciIo);
934 gBS->RestoreTPL (OldTpl);
935
936 if (EFI_ERROR (Status)) {
937 DEBUG ((DEBUG_ERROR, "EhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
938 }
939
940 return Status;
941 }
942
943
944 /**
945 Submits an asynchronous interrupt transfer to an
946 interrupt endpoint of a USB device.
947
948 @param This This EFI_USB2_HC_PROTOCOL instance.
949 @param DeviceAddress Target device address.
950 @param EndPointAddress Endpoint number and its direction encoded in bit 7
951 @param DeviceSpeed Indicates device speed.
952 @param MaximumPacketLength Maximum packet size the target endpoint is capable
953 @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt
954 transfer If FALSE, to remove the specified
955 asynchronous interrupt.
956 @param DataToggle On input, the initial data toggle to use; on output,
957 it is updated to indicate the next data toggle.
958 @param PollingInterval The he interval, in milliseconds, that the transfer
959 is polled.
960 @param DataLength The length of data to receive at the rate specified
961 by PollingInterval.
962 @param Translator Transaction translator to use.
963 @param CallBackFunction Function to call at the rate specified by
964 PollingInterval.
965 @param Context Context to CallBackFunction.
966
967 @retval EFI_SUCCESS The request has been successfully submitted or canceled.
968 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
969 @retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources.
970 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
971
972 **/
973 EFI_STATUS
974 EFIAPI
975 EhcAsyncInterruptTransfer (
976 IN EFI_USB2_HC_PROTOCOL * This,
977 IN UINT8 DeviceAddress,
978 IN UINT8 EndPointAddress,
979 IN UINT8 DeviceSpeed,
980 IN UINTN MaximumPacketLength,
981 IN BOOLEAN IsNewTransfer,
982 IN OUT UINT8 *DataToggle,
983 IN UINTN PollingInterval,
984 IN UINTN DataLength,
985 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,
986 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
987 IN VOID *Context OPTIONAL
988 )
989 {
990 USB2_HC_DEV *Ehc;
991 URB *Urb;
992 EFI_TPL OldTpl;
993 EFI_STATUS Status;
994
995 //
996 // Validate parameters
997 //
998 if (!EHCI_IS_DATAIN (EndPointAddress)) {
999 return EFI_INVALID_PARAMETER;
1000 }
1001
1002 if (IsNewTransfer) {
1003 if (DataLength == 0) {
1004 return EFI_INVALID_PARAMETER;
1005 }
1006
1007 if ((*DataToggle != 1) && (*DataToggle != 0)) {
1008 return EFI_INVALID_PARAMETER;
1009 }
1010
1011 if ((PollingInterval > 255) || (PollingInterval < 1)) {
1012 return EFI_INVALID_PARAMETER;
1013 }
1014 }
1015
1016 OldTpl = gBS->RaiseTPL (EHC_TPL);
1017 Ehc = EHC_FROM_THIS (This);
1018
1019 //
1020 // Delete Async interrupt transfer request. DataToggle will return
1021 // the next data toggle to use.
1022 //
1023 if (!IsNewTransfer) {
1024 Status = EhciDelAsyncIntTransfer (Ehc, DeviceAddress, EndPointAddress, DataToggle);
1025
1026 DEBUG ((DEBUG_INFO, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status));
1027 goto ON_EXIT;
1028 }
1029
1030 Status = EFI_SUCCESS;
1031
1032 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
1033 DEBUG ((DEBUG_ERROR, "EhcAsyncInterruptTransfer: HC is halt\n"));
1034 EhcAckAllInterrupt (Ehc);
1035
1036 Status = EFI_DEVICE_ERROR;
1037 goto ON_EXIT;
1038 }
1039
1040 EhcAckAllInterrupt (Ehc);
1041
1042 Urb = EhciInsertAsyncIntTransfer (
1043 Ehc,
1044 DeviceAddress,
1045 EndPointAddress,
1046 DeviceSpeed,
1047 *DataToggle,
1048 MaximumPacketLength,
1049 Translator,
1050 DataLength,
1051 CallBackFunction,
1052 Context,
1053 PollingInterval
1054 );
1055
1056 if (Urb == NULL) {
1057 Status = EFI_OUT_OF_RESOURCES;
1058 goto ON_EXIT;
1059 }
1060
1061 ON_EXIT:
1062 Ehc->PciIo->Flush (Ehc->PciIo);
1063 gBS->RestoreTPL (OldTpl);
1064
1065 return Status;
1066 }
1067
1068
1069 /**
1070 Submits synchronous interrupt transfer to an interrupt endpoint
1071 of a USB device.
1072
1073 @param This This EFI_USB2_HC_PROTOCOL instance.
1074 @param DeviceAddress Target device address.
1075 @param EndPointAddress Endpoint number and its direction encoded in bit 7
1076 @param DeviceSpeed Indicates device speed.
1077 @param MaximumPacketLength Maximum packet size the target endpoint is capable
1078 of sending or receiving.
1079 @param Data Buffer of data that will be transmitted to USB
1080 device or received from USB device.
1081 @param DataLength On input, the size, in bytes, of the data buffer; On
1082 output, the number of bytes transferred.
1083 @param DataToggle On input, the initial data toggle to use; on output,
1084 it is updated to indicate the next data toggle.
1085 @param TimeOut Maximum time, in second, to complete.
1086 @param Translator Transaction translator to use.
1087 @param TransferResult Variable to receive the transfer result.
1088
1089 @return EFI_SUCCESS The transfer was completed successfully.
1090 @return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
1091 @return EFI_INVALID_PARAMETER Some parameters are invalid.
1092 @return EFI_TIMEOUT The transfer failed due to timeout.
1093 @return EFI_DEVICE_ERROR The failed due to host controller or device error
1094
1095 **/
1096 EFI_STATUS
1097 EFIAPI
1098 EhcSyncInterruptTransfer (
1099 IN EFI_USB2_HC_PROTOCOL *This,
1100 IN UINT8 DeviceAddress,
1101 IN UINT8 EndPointAddress,
1102 IN UINT8 DeviceSpeed,
1103 IN UINTN MaximumPacketLength,
1104 IN OUT VOID *Data,
1105 IN OUT UINTN *DataLength,
1106 IN OUT UINT8 *DataToggle,
1107 IN UINTN TimeOut,
1108 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
1109 OUT UINT32 *TransferResult
1110 )
1111 {
1112 USB2_HC_DEV *Ehc;
1113 EFI_TPL OldTpl;
1114 URB *Urb;
1115 EFI_STATUS Status;
1116
1117 //
1118 // Validates parameters
1119 //
1120 if ((DataLength == NULL) || (*DataLength == 0) ||
1121 (Data == NULL) || (TransferResult == NULL)) {
1122 return EFI_INVALID_PARAMETER;
1123 }
1124
1125 if ((*DataToggle != 1) && (*DataToggle != 0)) {
1126 return EFI_INVALID_PARAMETER;
1127 }
1128
1129 if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) ||
1130 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
1131 ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) {
1132 return EFI_INVALID_PARAMETER;
1133 }
1134
1135 OldTpl = gBS->RaiseTPL (EHC_TPL);
1136 Ehc = EHC_FROM_THIS (This);
1137
1138 *TransferResult = EFI_USB_ERR_SYSTEM;
1139 Status = EFI_DEVICE_ERROR;
1140
1141 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
1142 DEBUG ((DEBUG_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));
1143
1144 EhcAckAllInterrupt (Ehc);
1145 goto ON_EXIT;
1146 }
1147
1148 EhcAckAllInterrupt (Ehc);
1149
1150 Urb = EhcCreateUrb (
1151 Ehc,
1152 DeviceAddress,
1153 EndPointAddress,
1154 DeviceSpeed,
1155 *DataToggle,
1156 MaximumPacketLength,
1157 Translator,
1158 EHC_INT_TRANSFER_SYNC,
1159 NULL,
1160 Data,
1161 *DataLength,
1162 NULL,
1163 NULL,
1164 1
1165 );
1166
1167 if (Urb == NULL) {
1168 DEBUG ((DEBUG_ERROR, "EhcSyncInterruptTransfer: failed to create URB\n"));
1169
1170 Status = EFI_OUT_OF_RESOURCES;
1171 goto ON_EXIT;
1172 }
1173
1174 EhcLinkQhToPeriod (Ehc, Urb->Qh);
1175 Status = EhcExecTransfer (Ehc, Urb, TimeOut);
1176 EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);
1177
1178 *TransferResult = Urb->Result;
1179 *DataLength = Urb->Completed;
1180 *DataToggle = Urb->DataToggle;
1181
1182 if (*TransferResult == EFI_USB_NOERROR) {
1183 Status = EFI_SUCCESS;
1184 }
1185
1186 EhcFreeUrb (Ehc, Urb);
1187 ON_EXIT:
1188 Ehc->PciIo->Flush (Ehc->PciIo);
1189 gBS->RestoreTPL (OldTpl);
1190
1191 if (EFI_ERROR (Status)) {
1192 DEBUG ((DEBUG_ERROR, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
1193 }
1194
1195 return Status;
1196 }
1197
1198
1199 /**
1200 Submits isochronous transfer to a target USB device.
1201
1202 @param This This EFI_USB2_HC_PROTOCOL instance.
1203 @param DeviceAddress Target device address.
1204 @param EndPointAddress End point address with its direction.
1205 @param DeviceSpeed Device speed, Low speed device doesn't support this
1206 type.
1207 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1208 sending or receiving.
1209 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1210 @param Data Array of pointers to the buffers of data that will
1211 be transmitted to USB device or received from USB
1212 device.
1213 @param DataLength The size, in bytes, of the data buffer.
1214 @param Translator Transaction translator to use.
1215 @param TransferResult Variable to receive the transfer result.
1216
1217 @return EFI_UNSUPPORTED Isochronous transfer is unsupported.
1218
1219 **/
1220 EFI_STATUS
1221 EFIAPI
1222 EhcIsochronousTransfer (
1223 IN EFI_USB2_HC_PROTOCOL *This,
1224 IN UINT8 DeviceAddress,
1225 IN UINT8 EndPointAddress,
1226 IN UINT8 DeviceSpeed,
1227 IN UINTN MaximumPacketLength,
1228 IN UINT8 DataBuffersNumber,
1229 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
1230 IN UINTN DataLength,
1231 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
1232 OUT UINT32 *TransferResult
1233 )
1234 {
1235 return EFI_UNSUPPORTED;
1236 }
1237
1238
1239 /**
1240 Submits Async isochronous transfer to a target USB device.
1241
1242 @param This This EFI_USB2_HC_PROTOCOL instance.
1243 @param DeviceAddress Target device address.
1244 @param EndPointAddress End point address with its direction.
1245 @param DeviceSpeed Device speed, Low speed device doesn't support this
1246 type.
1247 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1248 sending or receiving.
1249 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1250 @param Data Array of pointers to the buffers of data that will
1251 be transmitted to USB device or received from USB
1252 device.
1253 @param DataLength The size, in bytes, of the data buffer.
1254 @param Translator Transaction translator to use.
1255 @param IsochronousCallBack Function to be called when the transfer complete.
1256 @param Context Context passed to the call back function as
1257 parameter.
1258
1259 @return EFI_UNSUPPORTED Isochronous transfer isn't supported.
1260
1261 **/
1262 EFI_STATUS
1263 EFIAPI
1264 EhcAsyncIsochronousTransfer (
1265 IN EFI_USB2_HC_PROTOCOL *This,
1266 IN UINT8 DeviceAddress,
1267 IN UINT8 EndPointAddress,
1268 IN UINT8 DeviceSpeed,
1269 IN UINTN MaximumPacketLength,
1270 IN UINT8 DataBuffersNumber,
1271 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
1272 IN UINTN DataLength,
1273 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
1274 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
1275 IN VOID *Context
1276 )
1277 {
1278 return EFI_UNSUPPORTED;
1279 }
1280
1281 /**
1282 Entry point for EFI drivers.
1283
1284 @param ImageHandle EFI_HANDLE.
1285 @param SystemTable EFI_SYSTEM_TABLE.
1286
1287 @return EFI_SUCCESS Success.
1288 EFI_DEVICE_ERROR Fail.
1289
1290 **/
1291 EFI_STATUS
1292 EFIAPI
1293 EhcDriverEntryPoint (
1294 IN EFI_HANDLE ImageHandle,
1295 IN EFI_SYSTEM_TABLE *SystemTable
1296 )
1297 {
1298 return EfiLibInstallDriverBindingComponentName2 (
1299 ImageHandle,
1300 SystemTable,
1301 &gEhciDriverBinding,
1302 ImageHandle,
1303 &gEhciComponentName,
1304 &gEhciComponentName2
1305 );
1306 }
1307
1308
1309 /**
1310 Test to see if this driver supports ControllerHandle. Any
1311 ControllerHandle that has Usb2HcProtocol installed will
1312 be supported.
1313
1314 @param This Protocol instance pointer.
1315 @param Controller Handle of device to test.
1316 @param RemainingDevicePath Not used.
1317
1318 @return EFI_SUCCESS This driver supports this device.
1319 @return EFI_UNSUPPORTED This driver does not support this device.
1320
1321 **/
1322 EFI_STATUS
1323 EFIAPI
1324 EhcDriverBindingSupported (
1325 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1326 IN EFI_HANDLE Controller,
1327 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1328 )
1329 {
1330 EFI_STATUS Status;
1331 EFI_PCI_IO_PROTOCOL *PciIo;
1332 USB_CLASSC UsbClassCReg;
1333
1334 //
1335 // Test whether there is PCI IO Protocol attached on the controller handle.
1336 //
1337 Status = gBS->OpenProtocol (
1338 Controller,
1339 &gEfiPciIoProtocolGuid,
1340 (VOID **) &PciIo,
1341 This->DriverBindingHandle,
1342 Controller,
1343 EFI_OPEN_PROTOCOL_BY_DRIVER
1344 );
1345
1346 if (EFI_ERROR (Status)) {
1347 return EFI_UNSUPPORTED;
1348 }
1349
1350 Status = PciIo->Pci.Read (
1351 PciIo,
1352 EfiPciIoWidthUint8,
1353 PCI_CLASSCODE_OFFSET,
1354 sizeof (USB_CLASSC) / sizeof (UINT8),
1355 &UsbClassCReg
1356 );
1357
1358 if (EFI_ERROR (Status)) {
1359 Status = EFI_UNSUPPORTED;
1360 goto ON_EXIT;
1361 }
1362
1363 //
1364 // Test whether the controller belongs to Ehci type
1365 //
1366 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB)
1367 || ((UsbClassCReg.ProgInterface != PCI_IF_EHCI) && (UsbClassCReg.ProgInterface != PCI_IF_UHCI) && (UsbClassCReg.ProgInterface != PCI_IF_OHCI))) {
1368
1369 Status = EFI_UNSUPPORTED;
1370 }
1371
1372 ON_EXIT:
1373 gBS->CloseProtocol (
1374 Controller,
1375 &gEfiPciIoProtocolGuid,
1376 This->DriverBindingHandle,
1377 Controller
1378 );
1379
1380 return Status;
1381 }
1382
1383 /**
1384 Get the usb debug port related information.
1385
1386 @param Ehc The EHCI device.
1387
1388 @retval RETURN_SUCCESS Get debug port number, bar and offset successfully.
1389 @retval Others The usb host controller does not supported usb debug port capability.
1390
1391 **/
1392 EFI_STATUS
1393 EhcGetUsbDebugPortInfo (
1394 IN USB2_HC_DEV *Ehc
1395 )
1396 {
1397 EFI_PCI_IO_PROTOCOL *PciIo;
1398 UINT16 PciStatus;
1399 UINT8 CapabilityPtr;
1400 UINT8 CapabilityId;
1401 UINT16 DebugPort;
1402 EFI_STATUS Status;
1403
1404 ASSERT (Ehc->PciIo != NULL);
1405 PciIo = Ehc->PciIo;
1406
1407 //
1408 // Detect if the EHCI host controller support Capaility Pointer.
1409 //
1410 Status = PciIo->Pci.Read (
1411 PciIo,
1412 EfiPciIoWidthUint8,
1413 PCI_PRIMARY_STATUS_OFFSET,
1414 sizeof (UINT16),
1415 &PciStatus
1416 );
1417
1418 if (EFI_ERROR (Status)) {
1419 return Status;
1420 }
1421
1422 if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {
1423 //
1424 // The Pci Device Doesn't Support Capability Pointer.
1425 //
1426 return EFI_UNSUPPORTED;
1427 }
1428
1429 //
1430 // Get Pointer To Capability List
1431 //
1432 Status = PciIo->Pci.Read (
1433 PciIo,
1434 EfiPciIoWidthUint8,
1435 PCI_CAPBILITY_POINTER_OFFSET,
1436 1,
1437 &CapabilityPtr
1438 );
1439
1440 if (EFI_ERROR (Status)) {
1441 return Status;
1442 }
1443
1444 //
1445 // Find Capability ID 0xA, Which Is For Debug Port
1446 //
1447 while (CapabilityPtr != 0) {
1448 Status = PciIo->Pci.Read (
1449 PciIo,
1450 EfiPciIoWidthUint8,
1451 CapabilityPtr,
1452 1,
1453 &CapabilityId
1454 );
1455
1456 if (EFI_ERROR (Status)) {
1457 return Status;
1458 }
1459
1460 if (CapabilityId == EHC_DEBUG_PORT_CAP_ID) {
1461 break;
1462 }
1463
1464 Status = PciIo->Pci.Read (
1465 PciIo,
1466 EfiPciIoWidthUint8,
1467 CapabilityPtr + 1,
1468 1,
1469 &CapabilityPtr
1470 );
1471
1472 if (EFI_ERROR (Status)) {
1473 return Status;
1474 }
1475 }
1476
1477 //
1478 // No Debug Port Capability Found
1479 //
1480 if (CapabilityPtr == 0) {
1481 return EFI_UNSUPPORTED;
1482 }
1483
1484 //
1485 // Get The Base Address Of Debug Port Register In Debug Port Capability Register
1486 //
1487 Status = PciIo->Pci.Read (
1488 Ehc->PciIo,
1489 EfiPciIoWidthUint8,
1490 CapabilityPtr + 2,
1491 sizeof (UINT16),
1492 &DebugPort
1493 );
1494
1495 if (EFI_ERROR (Status)) {
1496 return Status;
1497 }
1498
1499 Ehc->DebugPortOffset = DebugPort & 0x1FFF;
1500 Ehc->DebugPortBarNum = (UINT8)((DebugPort >> 13) - 1);
1501 Ehc->DebugPortNum = (UINT8)((Ehc->HcStructParams & 0x00F00000) >> 20);
1502
1503 return EFI_SUCCESS;
1504 }
1505
1506
1507 /**
1508 Create and initialize a USB2_HC_DEV.
1509
1510 @param PciIo The PciIo on this device.
1511 @param DevicePath The device path of host controller.
1512 @param OriginalPciAttributes Original PCI attributes.
1513
1514 @return The allocated and initialized USB2_HC_DEV structure if created,
1515 otherwise NULL.
1516
1517 **/
1518 USB2_HC_DEV *
1519 EhcCreateUsb2Hc (
1520 IN EFI_PCI_IO_PROTOCOL *PciIo,
1521 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1522 IN UINT64 OriginalPciAttributes
1523 )
1524 {
1525 USB2_HC_DEV *Ehc;
1526 EFI_STATUS Status;
1527
1528 Ehc = AllocateZeroPool (sizeof (USB2_HC_DEV));
1529
1530 if (Ehc == NULL) {
1531 return NULL;
1532 }
1533
1534 //
1535 // Init EFI_USB2_HC_PROTOCOL interface and private data structure
1536 //
1537 Ehc->Signature = USB2_HC_DEV_SIGNATURE;
1538
1539 Ehc->Usb2Hc.GetCapability = EhcGetCapability;
1540 Ehc->Usb2Hc.Reset = EhcReset;
1541 Ehc->Usb2Hc.GetState = EhcGetState;
1542 Ehc->Usb2Hc.SetState = EhcSetState;
1543 Ehc->Usb2Hc.ControlTransfer = EhcControlTransfer;
1544 Ehc->Usb2Hc.BulkTransfer = EhcBulkTransfer;
1545 Ehc->Usb2Hc.AsyncInterruptTransfer = EhcAsyncInterruptTransfer;
1546 Ehc->Usb2Hc.SyncInterruptTransfer = EhcSyncInterruptTransfer;
1547 Ehc->Usb2Hc.IsochronousTransfer = EhcIsochronousTransfer;
1548 Ehc->Usb2Hc.AsyncIsochronousTransfer = EhcAsyncIsochronousTransfer;
1549 Ehc->Usb2Hc.GetRootHubPortStatus = EhcGetRootHubPortStatus;
1550 Ehc->Usb2Hc.SetRootHubPortFeature = EhcSetRootHubPortFeature;
1551 Ehc->Usb2Hc.ClearRootHubPortFeature = EhcClearRootHubPortFeature;
1552 Ehc->Usb2Hc.MajorRevision = 0x2;
1553 Ehc->Usb2Hc.MinorRevision = 0x0;
1554
1555 Ehc->PciIo = PciIo;
1556 Ehc->DevicePath = DevicePath;
1557 Ehc->OriginalPciAttributes = OriginalPciAttributes;
1558
1559 InitializeListHead (&Ehc->AsyncIntTransfers);
1560
1561 Ehc->HcStructParams = EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET);
1562 Ehc->HcCapParams = EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET);
1563 Ehc->CapLen = EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET) & 0x0FF;
1564
1565 DEBUG ((DEBUG_INFO, "EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen));
1566
1567 //
1568 // EHCI Controllers with a CapLen of 0 are ignored.
1569 //
1570 if (Ehc->CapLen == 0) {
1571 gBS->FreePool (Ehc);
1572 return NULL;
1573 }
1574
1575 EhcGetUsbDebugPortInfo (Ehc);
1576
1577 //
1578 // Create AsyncRequest Polling Timer
1579 //
1580 Status = gBS->CreateEvent (
1581 EVT_TIMER | EVT_NOTIFY_SIGNAL,
1582 TPL_NOTIFY,
1583 EhcMonitorAsyncRequests,
1584 Ehc,
1585 &Ehc->PollTimer
1586 );
1587
1588 if (EFI_ERROR (Status)) {
1589 gBS->FreePool (Ehc);
1590 return NULL;
1591 }
1592
1593 return Ehc;
1594 }
1595
1596 /**
1597 One notified function to stop the Host Controller when gBS->ExitBootServices() called.
1598
1599 @param Event Pointer to this event
1600 @param Context Event handler private data
1601
1602 **/
1603 VOID
1604 EFIAPI
1605 EhcExitBootService (
1606 EFI_EVENT Event,
1607 VOID *Context
1608 )
1609
1610 {
1611 USB2_HC_DEV *Ehc;
1612
1613 Ehc = (USB2_HC_DEV *) Context;
1614
1615 //
1616 // Reset the Host Controller
1617 //
1618 EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
1619 }
1620
1621
1622 /**
1623 Starting the Usb EHCI Driver.
1624
1625 @param This Protocol instance pointer.
1626 @param Controller Handle of device to test.
1627 @param RemainingDevicePath Not used.
1628
1629 @return EFI_SUCCESS supports this device.
1630 @return EFI_UNSUPPORTED do not support this device.
1631 @return EFI_DEVICE_ERROR cannot be started due to device Error.
1632 @return EFI_OUT_OF_RESOURCES cannot allocate resources.
1633
1634 **/
1635 EFI_STATUS
1636 EFIAPI
1637 EhcDriverBindingStart (
1638 IN EFI_DRIVER_BINDING_PROTOCOL *This,
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,
1699 EfiPciIoAttributeOperationGet,
1700 0,
1701 &OriginalPciAttributes
1702 );
1703
1704 if (EFI_ERROR (Status)) {
1705 goto CLOSE_PCIIO;
1706 }
1707 PciAttributesSaved = TRUE;
1708
1709 Status = PciIo->Attributes (
1710 PciIo,
1711 EfiPciIoAttributeOperationSupported,
1712 0,
1713 &Supports
1714 );
1715 if (!EFI_ERROR (Status)) {
1716 Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
1717 Status = PciIo->Attributes (
1718 PciIo,
1719 EfiPciIoAttributeOperationEnable,
1720 Supports,
1721 NULL
1722 );
1723 }
1724
1725 if (EFI_ERROR (Status)) {
1726 DEBUG ((DEBUG_ERROR, "EhcDriverBindingStart: failed to enable controller\n"));
1727 goto CLOSE_PCIIO;
1728 }
1729
1730 //
1731 // Get the Pci device class code.
1732 //
1733 Status = PciIo->Pci.Read (
1734 PciIo,
1735 EfiPciIoWidthUint8,
1736 PCI_CLASSCODE_OFFSET,
1737 sizeof (USB_CLASSC) / sizeof (UINT8),
1738 &UsbClassCReg
1739 );
1740
1741 if (EFI_ERROR (Status)) {
1742 Status = EFI_UNSUPPORTED;
1743 goto CLOSE_PCIIO;
1744 }
1745 //
1746 // Determine if the device is UHCI or OHCI host controller or not. If yes, then find out the
1747 // companion usb ehci host controller and force EHCI driver get attached to it before
1748 // UHCI or OHCI driver attaches to UHCI or OHCI host controller.
1749 //
1750 if ((UsbClassCReg.ProgInterface == PCI_IF_UHCI || UsbClassCReg.ProgInterface == PCI_IF_OHCI) &&
1751 (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
1752 (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
1753 Status = PciIo->GetLocation (
1754 PciIo,
1755 &CompanionSegmentNumber,
1756 &CompanionBusNumber,
1757 &CompanionDeviceNumber,
1758 &CompanionFunctionNumber
1759 );
1760 if (EFI_ERROR (Status)) {
1761 goto CLOSE_PCIIO;
1762 }
1763
1764 Status = gBS->LocateHandleBuffer (
1765 ByProtocol,
1766 &gEfiPciIoProtocolGuid,
1767 NULL,
1768 &NumberOfHandles,
1769 &HandleBuffer
1770 );
1771 if (EFI_ERROR (Status)) {
1772 goto CLOSE_PCIIO;
1773 }
1774
1775 for (Index = 0; Index < NumberOfHandles; Index++) {
1776 //
1777 // Get the device path on this handle
1778 //
1779 Status = gBS->HandleProtocol (
1780 HandleBuffer[Index],
1781 &gEfiPciIoProtocolGuid,
1782 (VOID **)&Instance
1783 );
1784 ASSERT_EFI_ERROR (Status);
1785
1786 Status = Instance->Pci.Read (
1787 Instance,
1788 EfiPciIoWidthUint8,
1789 PCI_CLASSCODE_OFFSET,
1790 sizeof (USB_CLASSC) / sizeof (UINT8),
1791 &UsbClassCReg
1792 );
1793
1794 if (EFI_ERROR (Status)) {
1795 Status = EFI_UNSUPPORTED;
1796 goto CLOSE_PCIIO;
1797 }
1798
1799 if ((UsbClassCReg.ProgInterface == PCI_IF_EHCI) &&
1800 (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
1801 (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
1802 Status = Instance->GetLocation (
1803 Instance,
1804 &EhciSegmentNumber,
1805 &EhciBusNumber,
1806 &EhciDeviceNumber,
1807 &EhciFunctionNumber
1808 );
1809 if (EFI_ERROR (Status)) {
1810 goto CLOSE_PCIIO;
1811 }
1812 //
1813 // Currently, the judgment on the companion usb host controller is through the
1814 // same bus number, which may vary on different platform.
1815 //
1816 if (EhciBusNumber == CompanionBusNumber) {
1817 gBS->CloseProtocol (
1818 Controller,
1819 &gEfiPciIoProtocolGuid,
1820 This->DriverBindingHandle,
1821 Controller
1822 );
1823 EhcDriverBindingStart(This, HandleBuffer[Index], NULL);
1824 }
1825 }
1826 }
1827 Status = EFI_NOT_FOUND;
1828 goto CLOSE_PCIIO;
1829 }
1830
1831 //
1832 // Create then install USB2_HC_PROTOCOL
1833 //
1834 Ehc = EhcCreateUsb2Hc (PciIo, HcDevicePath, OriginalPciAttributes);
1835
1836 if (Ehc == NULL) {
1837 DEBUG ((DEBUG_ERROR, "EhcDriverBindingStart: failed to create USB2_HC\n"));
1838
1839 Status = EFI_OUT_OF_RESOURCES;
1840 goto CLOSE_PCIIO;
1841 }
1842
1843 //
1844 // Enable 64-bit DMA support in the PCI layer if this controller
1845 // supports it.
1846 //
1847 if (EHC_BIT_IS_SET (Ehc->HcCapParams, HCCP_64BIT)) {
1848 Status = PciIo->Attributes (
1849 PciIo,
1850 EfiPciIoAttributeOperationEnable,
1851 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
1852 NULL
1853 );
1854 if (!EFI_ERROR (Status)) {
1855 Ehc->Support64BitDma = TRUE;
1856 } else {
1857 DEBUG ((DEBUG_WARN,
1858 "%a: failed to enable 64-bit DMA on 64-bit capable controller @ %p (%r)\n",
1859 __FUNCTION__, Controller, Status));
1860 }
1861 }
1862
1863 Status = gBS->InstallProtocolInterface (
1864 &Controller,
1865 &gEfiUsb2HcProtocolGuid,
1866 EFI_NATIVE_INTERFACE,
1867 &Ehc->Usb2Hc
1868 );
1869
1870 if (EFI_ERROR (Status)) {
1871 DEBUG ((DEBUG_ERROR, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
1872 goto FREE_POOL;
1873 }
1874
1875 //
1876 // Robustnesss improvement such as for Duet platform
1877 // Default is not required.
1878 //
1879 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
1880 EhcClearLegacySupport (Ehc);
1881 }
1882
1883 if (!EhcIsDebugPortInUse (Ehc, NULL)) {
1884 EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
1885 }
1886
1887 Status = EhcInitHC (Ehc);
1888
1889 if (EFI_ERROR (Status)) {
1890 DEBUG ((DEBUG_ERROR, "EhcDriverBindingStart: failed to init host controller\n"));
1891 goto UNINSTALL_USBHC;
1892 }
1893
1894 //
1895 // Start the asynchronous interrupt monitor
1896 //
1897 Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL);
1898
1899 if (EFI_ERROR (Status)) {
1900 DEBUG ((DEBUG_ERROR, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
1901
1902 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
1903 goto UNINSTALL_USBHC;
1904 }
1905
1906 //
1907 // Create event to stop the HC when exit boot service.
1908 //
1909 Status = gBS->CreateEventEx (
1910 EVT_NOTIFY_SIGNAL,
1911 TPL_NOTIFY,
1912 EhcExitBootService,
1913 Ehc,
1914 &gEfiEventExitBootServicesGuid,
1915 &Ehc->ExitBootServiceEvent
1916 );
1917 if (EFI_ERROR (Status)) {
1918 goto UNINSTALL_USBHC;
1919 }
1920
1921 //
1922 // Install the component name protocol, don't fail the start
1923 // because of something for display.
1924 //
1925 AddUnicodeString2 (
1926 "eng",
1927 gEhciComponentName.SupportedLanguages,
1928 &Ehc->ControllerNameTable,
1929 L"Enhanced Host Controller (USB 2.0)",
1930 TRUE
1931 );
1932 AddUnicodeString2 (
1933 "en",
1934 gEhciComponentName2.SupportedLanguages,
1935 &Ehc->ControllerNameTable,
1936 L"Enhanced Host Controller (USB 2.0)",
1937 FALSE
1938 );
1939
1940
1941 DEBUG ((DEBUG_INFO, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller));
1942 return EFI_SUCCESS;
1943
1944 UNINSTALL_USBHC:
1945 gBS->UninstallProtocolInterface (
1946 Controller,
1947 &gEfiUsb2HcProtocolGuid,
1948 &Ehc->Usb2Hc
1949 );
1950
1951 FREE_POOL:
1952 EhcFreeSched (Ehc);
1953 gBS->CloseEvent (Ehc->PollTimer);
1954 gBS->FreePool (Ehc);
1955
1956 CLOSE_PCIIO:
1957 if (PciAttributesSaved) {
1958 //
1959 // Restore original PCI attributes
1960 //
1961 PciIo->Attributes (
1962 PciIo,
1963 EfiPciIoAttributeOperationSet,
1964 OriginalPciAttributes,
1965 NULL
1966 );
1967 }
1968
1969 gBS->CloseProtocol (
1970 Controller,
1971 &gEfiPciIoProtocolGuid,
1972 This->DriverBindingHandle,
1973 Controller
1974 );
1975
1976 return Status;
1977 }
1978
1979
1980 /**
1981 Stop this driver on ControllerHandle. Support stopping any child handles
1982 created by this driver.
1983
1984 @param This Protocol instance pointer.
1985 @param Controller Handle of device to stop driver on.
1986 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
1987 @param ChildHandleBuffer List of handles for the children we need to stop.
1988
1989 @return EFI_SUCCESS Success.
1990 @return EFI_DEVICE_ERROR Fail.
1991
1992 **/
1993 EFI_STATUS
1994 EFIAPI
1995 EhcDriverBindingStop (
1996 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1997 IN EFI_HANDLE Controller,
1998 IN UINTN NumberOfChildren,
1999 IN EFI_HANDLE *ChildHandleBuffer
2000 )
2001 {
2002 EFI_STATUS Status;
2003 EFI_USB2_HC_PROTOCOL *Usb2Hc;
2004 EFI_PCI_IO_PROTOCOL *PciIo;
2005 USB2_HC_DEV *Ehc;
2006
2007 //
2008 // Test whether the Controller handler passed in is a valid
2009 // Usb controller handle that should be supported, if not,
2010 // return the error status directly
2011 //
2012 Status = gBS->OpenProtocol (
2013 Controller,
2014 &gEfiUsb2HcProtocolGuid,
2015 (VOID **) &Usb2Hc,
2016 This->DriverBindingHandle,
2017 Controller,
2018 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2019 );
2020
2021 if (EFI_ERROR (Status)) {
2022 return Status;
2023 }
2024
2025 Ehc = EHC_FROM_THIS (Usb2Hc);
2026 PciIo = Ehc->PciIo;
2027
2028 Status = gBS->UninstallProtocolInterface (
2029 Controller,
2030 &gEfiUsb2HcProtocolGuid,
2031 Usb2Hc
2032 );
2033
2034 if (EFI_ERROR (Status)) {
2035 return Status;
2036 }
2037
2038 //
2039 // Stop AsyncRequest Polling timer then stop the EHCI driver
2040 // and uninstall the EHCI protocl.
2041 //
2042 gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL);
2043 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
2044
2045 if (Ehc->PollTimer != NULL) {
2046 gBS->CloseEvent (Ehc->PollTimer);
2047 }
2048
2049 if (Ehc->ExitBootServiceEvent != NULL) {
2050 gBS->CloseEvent (Ehc->ExitBootServiceEvent);
2051 }
2052
2053 EhcFreeSched (Ehc);
2054
2055 if (Ehc->ControllerNameTable != NULL) {
2056 FreeUnicodeStringTable (Ehc->ControllerNameTable);
2057 }
2058
2059 //
2060 // Disable routing of all ports to EHCI controller, so all ports are
2061 // routed back to the UHCI or OHCI controller.
2062 //
2063 EhcClearOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
2064
2065 //
2066 // Restore original PCI attributes
2067 //
2068 PciIo->Attributes (
2069 PciIo,
2070 EfiPciIoAttributeOperationSet,
2071 Ehc->OriginalPciAttributes,
2072 NULL
2073 );
2074
2075 gBS->CloseProtocol (
2076 Controller,
2077 &gEfiPciIoProtocolGuid,
2078 This->DriverBindingHandle,
2079 Controller
2080 );
2081
2082 FreePool (Ehc);
2083
2084 return EFI_SUCCESS;
2085 }