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