]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
1) Add type cast for better coding style.
[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 - 2014, 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->HcCapParams & HCCP_64BIT);
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 (!EHCI_IS_DATAIN (EndPointAddress)) {
1163 return EFI_INVALID_PARAMETER;
1164 }
1165
1166 if ((*DataToggle != 1) && (*DataToggle != 0)) {
1167 return EFI_INVALID_PARAMETER;
1168 }
1169
1170 if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) ||
1171 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
1172 ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) {
1173 return EFI_INVALID_PARAMETER;
1174 }
1175
1176 OldTpl = gBS->RaiseTPL (EHC_TPL);
1177 Ehc = EHC_FROM_THIS (This);
1178
1179 *TransferResult = EFI_USB_ERR_SYSTEM;
1180 Status = EFI_DEVICE_ERROR;
1181
1182 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
1183 DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));
1184
1185 EhcAckAllInterrupt (Ehc);
1186 goto ON_EXIT;
1187 }
1188
1189 EhcAckAllInterrupt (Ehc);
1190
1191 Urb = EhcCreateUrb (
1192 Ehc,
1193 DeviceAddress,
1194 EndPointAddress,
1195 DeviceSpeed,
1196 *DataToggle,
1197 MaximumPacketLength,
1198 Translator,
1199 EHC_INT_TRANSFER_SYNC,
1200 NULL,
1201 Data,
1202 *DataLength,
1203 NULL,
1204 NULL,
1205 1
1206 );
1207
1208 if (Urb == NULL) {
1209 DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: failed to create URB\n"));
1210
1211 Status = EFI_OUT_OF_RESOURCES;
1212 goto ON_EXIT;
1213 }
1214
1215 EhcLinkQhToPeriod (Ehc, Urb->Qh);
1216 Status = EhcExecTransfer (Ehc, Urb, TimeOut);
1217 EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);
1218
1219 *TransferResult = Urb->Result;
1220 *DataLength = Urb->Completed;
1221 *DataToggle = Urb->DataToggle;
1222
1223 if (*TransferResult == EFI_USB_NOERROR) {
1224 Status = EFI_SUCCESS;
1225 }
1226
1227 ON_EXIT:
1228 Ehc->PciIo->Flush (Ehc->PciIo);
1229 gBS->RestoreTPL (OldTpl);
1230
1231 if (EFI_ERROR (Status)) {
1232 DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
1233 }
1234
1235 return Status;
1236 }
1237
1238
1239 /**
1240 Submits isochronous transfer to a target USB device.
1241
1242 @param This This EFI_USB2_HC_PROTOCOL instance.
1243 @param DeviceAddress Target device address.
1244 @param EndPointAddress End point address with its direction.
1245 @param DeviceSpeed Device speed, Low speed device doesn't support this
1246 type.
1247 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1248 sending or receiving.
1249 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1250 @param Data Array of pointers to the buffers of data that will
1251 be transmitted to USB device or received from USB
1252 device.
1253 @param DataLength The size, in bytes, of the data buffer.
1254 @param Translator Transaction translator to use.
1255 @param TransferResult Variable to receive the transfer result.
1256
1257 @return EFI_UNSUPPORTED Isochronous transfer is unsupported.
1258
1259 **/
1260 EFI_STATUS
1261 EFIAPI
1262 EhcIsochronousTransfer (
1263 IN EFI_USB2_HC_PROTOCOL *This,
1264 IN UINT8 DeviceAddress,
1265 IN UINT8 EndPointAddress,
1266 IN UINT8 DeviceSpeed,
1267 IN UINTN MaximumPacketLength,
1268 IN UINT8 DataBuffersNumber,
1269 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
1270 IN UINTN DataLength,
1271 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
1272 OUT UINT32 *TransferResult
1273 )
1274 {
1275 return EFI_UNSUPPORTED;
1276 }
1277
1278
1279 /**
1280 Submits Async isochronous transfer to a target USB device.
1281
1282 @param This This EFI_USB2_HC_PROTOCOL instance.
1283 @param DeviceAddress Target device address.
1284 @param EndPointAddress End point address with its direction.
1285 @param DeviceSpeed Device speed, Low speed device doesn't support this
1286 type.
1287 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1288 sending or receiving.
1289 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1290 @param Data Array of pointers to the buffers of data that will
1291 be transmitted to USB device or received from USB
1292 device.
1293 @param DataLength The size, in bytes, of the data buffer.
1294 @param Translator Transaction translator to use.
1295 @param IsochronousCallBack Function to be called when the transfer complete.
1296 @param Context Context passed to the call back function as
1297 parameter.
1298
1299 @return EFI_UNSUPPORTED Isochronous transfer isn't supported.
1300
1301 **/
1302 EFI_STATUS
1303 EFIAPI
1304 EhcAsyncIsochronousTransfer (
1305 IN EFI_USB2_HC_PROTOCOL *This,
1306 IN UINT8 DeviceAddress,
1307 IN UINT8 EndPointAddress,
1308 IN UINT8 DeviceSpeed,
1309 IN UINTN MaximumPacketLength,
1310 IN UINT8 DataBuffersNumber,
1311 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
1312 IN UINTN DataLength,
1313 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
1314 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
1315 IN VOID *Context
1316 )
1317 {
1318 return EFI_UNSUPPORTED;
1319 }
1320
1321 /**
1322 Entry point for EFI drivers.
1323
1324 @param ImageHandle EFI_HANDLE.
1325 @param SystemTable EFI_SYSTEM_TABLE.
1326
1327 @return EFI_SUCCESS Success.
1328 EFI_DEVICE_ERROR Fail.
1329
1330 **/
1331 EFI_STATUS
1332 EFIAPI
1333 EhcDriverEntryPoint (
1334 IN EFI_HANDLE ImageHandle,
1335 IN EFI_SYSTEM_TABLE *SystemTable
1336 )
1337 {
1338 return EfiLibInstallDriverBindingComponentName2 (
1339 ImageHandle,
1340 SystemTable,
1341 &gEhciDriverBinding,
1342 ImageHandle,
1343 &gEhciComponentName,
1344 &gEhciComponentName2
1345 );
1346 }
1347
1348
1349 /**
1350 Test to see if this driver supports ControllerHandle. Any
1351 ControllerHandle that has Usb2HcProtocol installed will
1352 be supported.
1353
1354 @param This Protocol instance pointer.
1355 @param Controller Handle of device to test.
1356 @param RemainingDevicePath Not used.
1357
1358 @return EFI_SUCCESS This driver supports this device.
1359 @return EFI_UNSUPPORTED This driver does not support this device.
1360
1361 **/
1362 EFI_STATUS
1363 EFIAPI
1364 EhcDriverBindingSupported (
1365 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1366 IN EFI_HANDLE Controller,
1367 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1368 )
1369 {
1370 EFI_STATUS Status;
1371 EFI_PCI_IO_PROTOCOL *PciIo;
1372 USB_CLASSC UsbClassCReg;
1373
1374 //
1375 // Test whether there is PCI IO Protocol attached on the controller handle.
1376 //
1377 Status = gBS->OpenProtocol (
1378 Controller,
1379 &gEfiPciIoProtocolGuid,
1380 (VOID **) &PciIo,
1381 This->DriverBindingHandle,
1382 Controller,
1383 EFI_OPEN_PROTOCOL_BY_DRIVER
1384 );
1385
1386 if (EFI_ERROR (Status)) {
1387 return EFI_UNSUPPORTED;
1388 }
1389
1390 Status = PciIo->Pci.Read (
1391 PciIo,
1392 EfiPciIoWidthUint8,
1393 PCI_CLASSCODE_OFFSET,
1394 sizeof (USB_CLASSC) / sizeof (UINT8),
1395 &UsbClassCReg
1396 );
1397
1398 if (EFI_ERROR (Status)) {
1399 Status = EFI_UNSUPPORTED;
1400 goto ON_EXIT;
1401 }
1402
1403 //
1404 // Test whether the controller belongs to Ehci type
1405 //
1406 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB)
1407 || ((UsbClassCReg.ProgInterface != PCI_IF_EHCI) && (UsbClassCReg.ProgInterface != PCI_IF_UHCI) && (UsbClassCReg.ProgInterface != PCI_IF_OHCI))) {
1408
1409 Status = EFI_UNSUPPORTED;
1410 }
1411
1412 ON_EXIT:
1413 gBS->CloseProtocol (
1414 Controller,
1415 &gEfiPciIoProtocolGuid,
1416 This->DriverBindingHandle,
1417 Controller
1418 );
1419
1420 return Status;
1421 }
1422
1423 /**
1424 Get the usb debug port related information.
1425
1426 @param Ehc The EHCI device.
1427
1428 @retval RETURN_SUCCESS Get debug port number, bar and offset successfully.
1429 @retval Others The usb host controller does not supported usb debug port capability.
1430
1431 **/
1432 EFI_STATUS
1433 EhcGetUsbDebugPortInfo (
1434 IN USB2_HC_DEV *Ehc
1435 )
1436 {
1437 EFI_PCI_IO_PROTOCOL *PciIo;
1438 UINT16 PciStatus;
1439 UINT8 CapabilityPtr;
1440 UINT8 CapabilityId;
1441 UINT16 DebugPort;
1442 EFI_STATUS Status;
1443
1444 ASSERT (Ehc->PciIo != NULL);
1445 PciIo = Ehc->PciIo;
1446
1447 //
1448 // Detect if the EHCI host controller support Capaility Pointer.
1449 //
1450 Status = PciIo->Pci.Read (
1451 PciIo,
1452 EfiPciIoWidthUint8,
1453 PCI_PRIMARY_STATUS_OFFSET,
1454 sizeof (UINT16),
1455 &PciStatus
1456 );
1457
1458 if (EFI_ERROR (Status)) {
1459 return Status;
1460 }
1461
1462 if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {
1463 //
1464 // The Pci Device Doesn't Support Capability Pointer.
1465 //
1466 return EFI_UNSUPPORTED;
1467 }
1468
1469 //
1470 // Get Pointer To Capability List
1471 //
1472 Status = PciIo->Pci.Read (
1473 PciIo,
1474 EfiPciIoWidthUint8,
1475 PCI_CAPBILITY_POINTER_OFFSET,
1476 1,
1477 &CapabilityPtr
1478 );
1479
1480 if (EFI_ERROR (Status)) {
1481 return Status;
1482 }
1483
1484 //
1485 // Find Capability ID 0xA, Which Is For Debug Port
1486 //
1487 while (CapabilityPtr != 0) {
1488 Status = PciIo->Pci.Read (
1489 PciIo,
1490 EfiPciIoWidthUint8,
1491 CapabilityPtr,
1492 1,
1493 &CapabilityId
1494 );
1495
1496 if (EFI_ERROR (Status)) {
1497 return Status;
1498 }
1499
1500 if (CapabilityId == EHC_DEBUG_PORT_CAP_ID) {
1501 break;
1502 }
1503
1504 Status = PciIo->Pci.Read (
1505 PciIo,
1506 EfiPciIoWidthUint8,
1507 CapabilityPtr + 1,
1508 1,
1509 &CapabilityPtr
1510 );
1511
1512 if (EFI_ERROR (Status)) {
1513 return Status;
1514 }
1515 }
1516
1517 //
1518 // No Debug Port Capability Found
1519 //
1520 if (CapabilityPtr == 0) {
1521 return EFI_UNSUPPORTED;
1522 }
1523
1524 //
1525 // Get The Base Address Of Debug Port Register In Debug Port Capability Register
1526 //
1527 Status = PciIo->Pci.Read (
1528 Ehc->PciIo,
1529 EfiPciIoWidthUint8,
1530 CapabilityPtr + 2,
1531 sizeof (UINT16),
1532 &DebugPort
1533 );
1534
1535 if (EFI_ERROR (Status)) {
1536 return Status;
1537 }
1538
1539 Ehc->DebugPortOffset = DebugPort & 0x1FFF;
1540 Ehc->DebugPortBarNum = (UINT8)((DebugPort >> 13) - 1);
1541 Ehc->DebugPortNum = (UINT8)((Ehc->HcStructParams & 0x00F00000) >> 20);
1542
1543 return EFI_SUCCESS;
1544 }
1545
1546
1547 /**
1548 Create and initialize a USB2_HC_DEV.
1549
1550 @param PciIo The PciIo on this device.
1551 @param DevicePath The device path of host controller.
1552 @param OriginalPciAttributes Original PCI attributes.
1553
1554 @return The allocated and initialized USB2_HC_DEV structure if created,
1555 otherwise NULL.
1556
1557 **/
1558 USB2_HC_DEV *
1559 EhcCreateUsb2Hc (
1560 IN EFI_PCI_IO_PROTOCOL *PciIo,
1561 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1562 IN UINT64 OriginalPciAttributes
1563 )
1564 {
1565 USB2_HC_DEV *Ehc;
1566 EFI_STATUS Status;
1567
1568 Ehc = AllocateZeroPool (sizeof (USB2_HC_DEV));
1569
1570 if (Ehc == NULL) {
1571 return NULL;
1572 }
1573
1574 //
1575 // Init EFI_USB2_HC_PROTOCOL interface and private data structure
1576 //
1577 Ehc->Signature = USB2_HC_DEV_SIGNATURE;
1578
1579 Ehc->Usb2Hc.GetCapability = EhcGetCapability;
1580 Ehc->Usb2Hc.Reset = EhcReset;
1581 Ehc->Usb2Hc.GetState = EhcGetState;
1582 Ehc->Usb2Hc.SetState = EhcSetState;
1583 Ehc->Usb2Hc.ControlTransfer = EhcControlTransfer;
1584 Ehc->Usb2Hc.BulkTransfer = EhcBulkTransfer;
1585 Ehc->Usb2Hc.AsyncInterruptTransfer = EhcAsyncInterruptTransfer;
1586 Ehc->Usb2Hc.SyncInterruptTransfer = EhcSyncInterruptTransfer;
1587 Ehc->Usb2Hc.IsochronousTransfer = EhcIsochronousTransfer;
1588 Ehc->Usb2Hc.AsyncIsochronousTransfer = EhcAsyncIsochronousTransfer;
1589 Ehc->Usb2Hc.GetRootHubPortStatus = EhcGetRootHubPortStatus;
1590 Ehc->Usb2Hc.SetRootHubPortFeature = EhcSetRootHubPortFeature;
1591 Ehc->Usb2Hc.ClearRootHubPortFeature = EhcClearRootHubPortFeature;
1592 Ehc->Usb2Hc.MajorRevision = 0x2;
1593 Ehc->Usb2Hc.MinorRevision = 0x0;
1594
1595 Ehc->PciIo = PciIo;
1596 Ehc->DevicePath = DevicePath;
1597 Ehc->OriginalPciAttributes = OriginalPciAttributes;
1598
1599 InitializeListHead (&Ehc->AsyncIntTransfers);
1600
1601 Ehc->HcStructParams = EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET);
1602 Ehc->HcCapParams = EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET);
1603 Ehc->CapLen = EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET) & 0x0FF;
1604
1605 DEBUG ((EFI_D_INFO, "EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen));
1606
1607 //
1608 // EHCI Controllers with a CapLen of 0 are ignored.
1609 //
1610 if (Ehc->CapLen == 0) {
1611 gBS->FreePool (Ehc);
1612 return NULL;
1613 }
1614
1615 EhcGetUsbDebugPortInfo (Ehc);
1616
1617 //
1618 // Create AsyncRequest Polling Timer
1619 //
1620 Status = gBS->CreateEvent (
1621 EVT_TIMER | EVT_NOTIFY_SIGNAL,
1622 TPL_CALLBACK,
1623 EhcMonitorAsyncRequests,
1624 Ehc,
1625 &Ehc->PollTimer
1626 );
1627
1628 if (EFI_ERROR (Status)) {
1629 gBS->FreePool (Ehc);
1630 return NULL;
1631 }
1632
1633 return Ehc;
1634 }
1635
1636 /**
1637 One notified function to stop the Host Controller when gBS->ExitBootServices() called.
1638
1639 @param Event Pointer to this event
1640 @param Context Event handler private data
1641
1642 **/
1643 VOID
1644 EFIAPI
1645 EhcExitBootService (
1646 EFI_EVENT Event,
1647 VOID *Context
1648 )
1649
1650 {
1651 USB2_HC_DEV *Ehc;
1652
1653 Ehc = (USB2_HC_DEV *) Context;
1654
1655 //
1656 // Reset the Host Controller
1657 //
1658 EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
1659 }
1660
1661
1662 /**
1663 Starting the Usb EHCI Driver.
1664
1665 @param This Protocol instance pointer.
1666 @param Controller Handle of device to test.
1667 @param RemainingDevicePath Not used.
1668
1669 @return EFI_SUCCESS supports this device.
1670 @return EFI_UNSUPPORTED do not support this device.
1671 @return EFI_DEVICE_ERROR cannot be started due to device Error.
1672 @return EFI_OUT_OF_RESOURCES cannot allocate resources.
1673
1674 **/
1675 EFI_STATUS
1676 EFIAPI
1677 EhcDriverBindingStart (
1678 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1679 IN EFI_HANDLE Controller,
1680 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1681 )
1682 {
1683 EFI_STATUS Status;
1684 USB2_HC_DEV *Ehc;
1685 EFI_PCI_IO_PROTOCOL *PciIo;
1686 EFI_PCI_IO_PROTOCOL *Instance;
1687 UINT64 Supports;
1688 UINT64 OriginalPciAttributes;
1689 BOOLEAN PciAttributesSaved;
1690 USB_CLASSC UsbClassCReg;
1691 EFI_HANDLE *HandleBuffer;
1692 UINTN NumberOfHandles;
1693 UINTN Index;
1694 UINTN CompanionSegmentNumber;
1695 UINTN CompanionBusNumber;
1696 UINTN CompanionDeviceNumber;
1697 UINTN CompanionFunctionNumber;
1698 UINTN EhciSegmentNumber;
1699 UINTN EhciBusNumber;
1700 UINTN EhciDeviceNumber;
1701 UINTN EhciFunctionNumber;
1702 UINT32 State;
1703 EFI_DEVICE_PATH_PROTOCOL *HcDevicePath;
1704
1705 //
1706 // Open the PciIo Protocol, then enable the USB host controller
1707 //
1708 Status = gBS->OpenProtocol (
1709 Controller,
1710 &gEfiPciIoProtocolGuid,
1711 (VOID **) &PciIo,
1712 This->DriverBindingHandle,
1713 Controller,
1714 EFI_OPEN_PROTOCOL_BY_DRIVER
1715 );
1716
1717 if (EFI_ERROR (Status)) {
1718 return Status;
1719 }
1720
1721 //
1722 // Open Device Path Protocol for on USB host controller
1723 //
1724 HcDevicePath = NULL;
1725 Status = gBS->OpenProtocol (
1726 Controller,
1727 &gEfiDevicePathProtocolGuid,
1728 (VOID **) &HcDevicePath,
1729 This->DriverBindingHandle,
1730 Controller,
1731 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1732 );
1733
1734 PciAttributesSaved = FALSE;
1735 //
1736 // Save original PCI attributes
1737 //
1738 Status = PciIo->Attributes (
1739 PciIo,
1740 EfiPciIoAttributeOperationGet,
1741 0,
1742 &OriginalPciAttributes
1743 );
1744
1745 if (EFI_ERROR (Status)) {
1746 goto CLOSE_PCIIO;
1747 }
1748 PciAttributesSaved = TRUE;
1749
1750 Status = PciIo->Attributes (
1751 PciIo,
1752 EfiPciIoAttributeOperationSupported,
1753 0,
1754 &Supports
1755 );
1756 if (!EFI_ERROR (Status)) {
1757 Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
1758 Status = PciIo->Attributes (
1759 PciIo,
1760 EfiPciIoAttributeOperationEnable,
1761 Supports,
1762 NULL
1763 );
1764 }
1765
1766 if (EFI_ERROR (Status)) {
1767 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to enable controller\n"));
1768 goto CLOSE_PCIIO;
1769 }
1770
1771 //
1772 // Get the Pci device class code.
1773 //
1774 Status = PciIo->Pci.Read (
1775 PciIo,
1776 EfiPciIoWidthUint8,
1777 PCI_CLASSCODE_OFFSET,
1778 sizeof (USB_CLASSC) / sizeof (UINT8),
1779 &UsbClassCReg
1780 );
1781
1782 if (EFI_ERROR (Status)) {
1783 Status = EFI_UNSUPPORTED;
1784 goto CLOSE_PCIIO;
1785 }
1786 //
1787 // Determine if the device is UHCI or OHCI host controller or not. If yes, then find out the
1788 // companion usb ehci host controller and force EHCI driver get attached to it before
1789 // UHCI or OHCI driver attaches to UHCI or OHCI host controller.
1790 //
1791 if ((UsbClassCReg.ProgInterface == PCI_IF_UHCI || UsbClassCReg.ProgInterface == PCI_IF_OHCI) &&
1792 (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
1793 (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
1794 Status = PciIo->GetLocation (
1795 PciIo,
1796 &CompanionSegmentNumber,
1797 &CompanionBusNumber,
1798 &CompanionDeviceNumber,
1799 &CompanionFunctionNumber
1800 );
1801 if (EFI_ERROR (Status)) {
1802 goto CLOSE_PCIIO;
1803 }
1804
1805 Status = gBS->LocateHandleBuffer (
1806 ByProtocol,
1807 &gEfiPciIoProtocolGuid,
1808 NULL,
1809 &NumberOfHandles,
1810 &HandleBuffer
1811 );
1812 if (EFI_ERROR (Status)) {
1813 goto CLOSE_PCIIO;
1814 }
1815
1816 for (Index = 0; Index < NumberOfHandles; Index++) {
1817 //
1818 // Get the device path on this handle
1819 //
1820 Status = gBS->HandleProtocol (
1821 HandleBuffer[Index],
1822 &gEfiPciIoProtocolGuid,
1823 (VOID **)&Instance
1824 );
1825 ASSERT_EFI_ERROR (Status);
1826
1827 Status = Instance->Pci.Read (
1828 Instance,
1829 EfiPciIoWidthUint8,
1830 PCI_CLASSCODE_OFFSET,
1831 sizeof (USB_CLASSC) / sizeof (UINT8),
1832 &UsbClassCReg
1833 );
1834
1835 if (EFI_ERROR (Status)) {
1836 Status = EFI_UNSUPPORTED;
1837 goto CLOSE_PCIIO;
1838 }
1839
1840 if ((UsbClassCReg.ProgInterface == PCI_IF_EHCI) &&
1841 (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
1842 (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
1843 Status = Instance->GetLocation (
1844 Instance,
1845 &EhciSegmentNumber,
1846 &EhciBusNumber,
1847 &EhciDeviceNumber,
1848 &EhciFunctionNumber
1849 );
1850 if (EFI_ERROR (Status)) {
1851 goto CLOSE_PCIIO;
1852 }
1853 //
1854 // Currently, the judgment on the companion usb host controller is through the
1855 // same bus number, which may vary on different platform.
1856 //
1857 if (EhciBusNumber == CompanionBusNumber) {
1858 gBS->CloseProtocol (
1859 Controller,
1860 &gEfiPciIoProtocolGuid,
1861 This->DriverBindingHandle,
1862 Controller
1863 );
1864 EhcDriverBindingStart(This, HandleBuffer[Index], NULL);
1865 }
1866 }
1867 }
1868 Status = EFI_NOT_FOUND;
1869 goto CLOSE_PCIIO;
1870 }
1871
1872 //
1873 // Create then install USB2_HC_PROTOCOL
1874 //
1875 Ehc = EhcCreateUsb2Hc (PciIo, HcDevicePath, OriginalPciAttributes);
1876
1877 if (Ehc == NULL) {
1878 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to create USB2_HC\n"));
1879
1880 Status = EFI_OUT_OF_RESOURCES;
1881 goto CLOSE_PCIIO;
1882 }
1883
1884 Status = gBS->InstallProtocolInterface (
1885 &Controller,
1886 &gEfiUsb2HcProtocolGuid,
1887 EFI_NATIVE_INTERFACE,
1888 &Ehc->Usb2Hc
1889 );
1890
1891 if (EFI_ERROR (Status)) {
1892 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
1893 goto FREE_POOL;
1894 }
1895
1896 //
1897 // Robustnesss improvement such as for Duet platform
1898 // Default is not required.
1899 //
1900 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
1901 EhcClearLegacySupport (Ehc);
1902 }
1903
1904 if (Ehc->DebugPortNum != 0) {
1905 State = EhcReadDbgRegister(Ehc, 0);
1906 if ((State & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) != (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) {
1907 EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
1908 }
1909 }
1910
1911 Status = EhcInitHC (Ehc);
1912
1913 if (EFI_ERROR (Status)) {
1914 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to init host controller\n"));
1915 goto UNINSTALL_USBHC;
1916 }
1917
1918 //
1919 // Start the asynchronous interrupt monitor
1920 //
1921 Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL);
1922
1923 if (EFI_ERROR (Status)) {
1924 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
1925
1926 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
1927 goto UNINSTALL_USBHC;
1928 }
1929
1930 //
1931 // Create event to stop the HC when exit boot service.
1932 //
1933 Status = gBS->CreateEventEx (
1934 EVT_NOTIFY_SIGNAL,
1935 TPL_NOTIFY,
1936 EhcExitBootService,
1937 Ehc,
1938 &gEfiEventExitBootServicesGuid,
1939 &Ehc->ExitBootServiceEvent
1940 );
1941 if (EFI_ERROR (Status)) {
1942 goto UNINSTALL_USBHC;
1943 }
1944
1945 //
1946 // Install the component name protocol, don't fail the start
1947 // because of something for display.
1948 //
1949 AddUnicodeString2 (
1950 "eng",
1951 gEhciComponentName.SupportedLanguages,
1952 &Ehc->ControllerNameTable,
1953 L"Enhanced Host Controller (USB 2.0)",
1954 TRUE
1955 );
1956 AddUnicodeString2 (
1957 "en",
1958 gEhciComponentName2.SupportedLanguages,
1959 &Ehc->ControllerNameTable,
1960 L"Enhanced Host Controller (USB 2.0)",
1961 FALSE
1962 );
1963
1964
1965 DEBUG ((EFI_D_INFO, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller));
1966 return EFI_SUCCESS;
1967
1968 UNINSTALL_USBHC:
1969 gBS->UninstallProtocolInterface (
1970 Controller,
1971 &gEfiUsb2HcProtocolGuid,
1972 &Ehc->Usb2Hc
1973 );
1974
1975 FREE_POOL:
1976 EhcFreeSched (Ehc);
1977 gBS->CloseEvent (Ehc->PollTimer);
1978 gBS->FreePool (Ehc);
1979
1980 CLOSE_PCIIO:
1981 if (PciAttributesSaved) {
1982 //
1983 // Restore original PCI attributes
1984 //
1985 PciIo->Attributes (
1986 PciIo,
1987 EfiPciIoAttributeOperationSet,
1988 OriginalPciAttributes,
1989 NULL
1990 );
1991 }
1992
1993 gBS->CloseProtocol (
1994 Controller,
1995 &gEfiPciIoProtocolGuid,
1996 This->DriverBindingHandle,
1997 Controller
1998 );
1999
2000 return Status;
2001 }
2002
2003
2004 /**
2005 Stop this driver on ControllerHandle. Support stoping any child handles
2006 created by this driver.
2007
2008 @param This Protocol instance pointer.
2009 @param Controller Handle of device to stop driver on.
2010 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
2011 @param ChildHandleBuffer List of handles for the children we need to stop.
2012
2013 @return EFI_SUCCESS Success.
2014 @return EFI_DEVICE_ERROR Fail.
2015
2016 **/
2017 EFI_STATUS
2018 EFIAPI
2019 EhcDriverBindingStop (
2020 IN EFI_DRIVER_BINDING_PROTOCOL *This,
2021 IN EFI_HANDLE Controller,
2022 IN UINTN NumberOfChildren,
2023 IN EFI_HANDLE *ChildHandleBuffer
2024 )
2025 {
2026 EFI_STATUS Status;
2027 EFI_USB2_HC_PROTOCOL *Usb2Hc;
2028 EFI_PCI_IO_PROTOCOL *PciIo;
2029 USB2_HC_DEV *Ehc;
2030
2031 //
2032 // Test whether the Controller handler passed in is a valid
2033 // Usb controller handle that should be supported, if not,
2034 // return the error status directly
2035 //
2036 Status = gBS->OpenProtocol (
2037 Controller,
2038 &gEfiUsb2HcProtocolGuid,
2039 (VOID **) &Usb2Hc,
2040 This->DriverBindingHandle,
2041 Controller,
2042 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2043 );
2044
2045 if (EFI_ERROR (Status)) {
2046 return Status;
2047 }
2048
2049 Ehc = EHC_FROM_THIS (Usb2Hc);
2050 PciIo = Ehc->PciIo;
2051
2052 Status = gBS->UninstallProtocolInterface (
2053 Controller,
2054 &gEfiUsb2HcProtocolGuid,
2055 Usb2Hc
2056 );
2057
2058 if (EFI_ERROR (Status)) {
2059 return Status;
2060 }
2061
2062 //
2063 // Stop AsyncRequest Polling timer then stop the EHCI driver
2064 // and uninstall the EHCI protocl.
2065 //
2066 gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL);
2067 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
2068
2069 if (Ehc->PollTimer != NULL) {
2070 gBS->CloseEvent (Ehc->PollTimer);
2071 }
2072
2073 if (Ehc->ExitBootServiceEvent != NULL) {
2074 gBS->CloseEvent (Ehc->ExitBootServiceEvent);
2075 }
2076
2077 EhcFreeSched (Ehc);
2078
2079 if (Ehc->ControllerNameTable != NULL) {
2080 FreeUnicodeStringTable (Ehc->ControllerNameTable);
2081 }
2082
2083 //
2084 // Disable routing of all ports to EHCI controller, so all ports are
2085 // routed back to the UHCI or OHCI controller.
2086 //
2087 EhcClearOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
2088
2089 //
2090 // Restore original PCI attributes
2091 //
2092 PciIo->Attributes (
2093 PciIo,
2094 EfiPciIoAttributeOperationSet,
2095 Ehc->OriginalPciAttributes,
2096 NULL
2097 );
2098
2099 gBS->CloseProtocol (
2100 Controller,
2101 &gEfiPciIoProtocolGuid,
2102 This->DriverBindingHandle,
2103 Controller
2104 );
2105
2106 FreePool (Ehc);
2107
2108 return EFI_SUCCESS;
2109 }
2110