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