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