]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
EHCI Controllers with a CapLen of 0 are ignored.
[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 - 2010, 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 CONST 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 CONST EFI_USB2_HC_PROTOCOL *This,
314 IN CONST 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 // Not supported, ignore the operation
473 //
474 Status = EFI_SUCCESS;
475 break;
476
477 case EfiUsbPortOwner:
478 State |= PORTSC_OWNER;
479 EhcWriteOpReg (Ehc, Offset, State);
480 break;
481
482 default:
483 Status = EFI_INVALID_PARAMETER;
484 }
485
486 ON_EXIT:
487 DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature: exit status %r\n", Status));
488
489 gBS->RestoreTPL (OldTpl);
490 return Status;
491 }
492
493
494 /**
495 Clears a feature for the specified root hub port.
496
497 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
498 @param PortNumber Specifies the root hub port whose feature is
499 requested to be cleared.
500 @param PortFeature Indicates the feature selector associated with the
501 feature clear request.
502
503 @retval EFI_SUCCESS The feature specified by PortFeature was cleared
504 for the USB root hub port specified by PortNumber.
505 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
506 @retval EFI_DEVICE_ERROR Can't read register.
507
508 **/
509 EFI_STATUS
510 EFIAPI
511 EhcClearRootHubPortFeature (
512 IN EFI_USB2_HC_PROTOCOL *This,
513 IN UINT8 PortNumber,
514 IN EFI_USB_PORT_FEATURE PortFeature
515 )
516 {
517 USB2_HC_DEV *Ehc;
518 EFI_TPL OldTpl;
519 UINT32 Offset;
520 UINT32 State;
521 UINT32 TotalPort;
522 EFI_STATUS Status;
523
524 OldTpl = gBS->RaiseTPL (EHC_TPL);
525 Ehc = EHC_FROM_THIS (This);
526 Status = EFI_SUCCESS;
527
528 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
529
530 if (PortNumber >= TotalPort) {
531 Status = EFI_INVALID_PARAMETER;
532 goto ON_EXIT;
533 }
534
535 Offset = EHC_PORT_STAT_OFFSET + (4 * PortNumber);
536 State = EhcReadOpReg (Ehc, Offset);
537 State &= ~PORTSC_CHANGE_MASK;
538
539 switch (PortFeature) {
540 case EfiUsbPortEnable:
541 //
542 // Clear PORT_ENABLE feature means disable port.
543 //
544 State &= ~PORTSC_ENABLED;
545 EhcWriteOpReg (Ehc, Offset, State);
546 break;
547
548 case EfiUsbPortSuspend:
549 //
550 // A write of zero to this bit is ignored by the host
551 // controller. The host controller will unconditionally
552 // set this bit to a zero when:
553 // 1. software sets the Forct Port Resume bit to a zero from a one.
554 // 2. software sets the Port Reset bit to a one frome a zero.
555 //
556 State &= ~PORSTSC_RESUME;
557 EhcWriteOpReg (Ehc, Offset, State);
558 break;
559
560 case EfiUsbPortReset:
561 //
562 // Clear PORT_RESET means clear the reset signal.
563 //
564 State &= ~PORTSC_RESET;
565 EhcWriteOpReg (Ehc, Offset, State);
566 break;
567
568 case EfiUsbPortOwner:
569 //
570 // Clear port owner means this port owned by EHC
571 //
572 State &= ~PORTSC_OWNER;
573 EhcWriteOpReg (Ehc, Offset, State);
574 break;
575
576 case EfiUsbPortConnectChange:
577 //
578 // Clear connect status change
579 //
580 State |= PORTSC_CONN_CHANGE;
581 EhcWriteOpReg (Ehc, Offset, State);
582 break;
583
584 case EfiUsbPortEnableChange:
585 //
586 // Clear enable status change
587 //
588 State |= PORTSC_ENABLE_CHANGE;
589 EhcWriteOpReg (Ehc, Offset, State);
590 break;
591
592 case EfiUsbPortOverCurrentChange:
593 //
594 // Clear PortOverCurrent change
595 //
596 State |= PORTSC_OVERCUR_CHANGE;
597 EhcWriteOpReg (Ehc, Offset, State);
598 break;
599
600 case EfiUsbPortPower:
601 case EfiUsbPortSuspendChange:
602 case EfiUsbPortResetChange:
603 //
604 // Not supported or not related operation
605 //
606 break;
607
608 default:
609 Status = EFI_INVALID_PARAMETER;
610 break;
611 }
612
613 ON_EXIT:
614 DEBUG ((EFI_D_INFO, "EhcClearRootHubPortFeature: exit status %r\n", Status));
615 gBS->RestoreTPL (OldTpl);
616 return Status;
617 }
618
619
620 /**
621 Submits control transfer to a target USB device.
622
623 @param This This EFI_USB2_HC_PROTOCOL instance.
624 @param DeviceAddress The target device address.
625 @param DeviceSpeed Target device speed.
626 @param MaximumPacketLength Maximum packet size the default control transfer
627 endpoint is capable of sending or receiving.
628 @param Request USB device request to send.
629 @param TransferDirection Specifies the data direction for the data stage
630 @param Data Data buffer to be transmitted or received from USB
631 device.
632 @param DataLength The size (in bytes) of the data buffer.
633 @param TimeOut Indicates the maximum timeout, in millisecond.
634 @param Translator Transaction translator to be used by this device.
635 @param TransferResult Return the result of this control transfer.
636
637 @retval EFI_SUCCESS Transfer was completed successfully.
638 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
639 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
640 @retval EFI_TIMEOUT Transfer failed due to timeout.
641 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
642
643 **/
644 EFI_STATUS
645 EFIAPI
646 EhcControlTransfer (
647 IN EFI_USB2_HC_PROTOCOL *This,
648 IN UINT8 DeviceAddress,
649 IN UINT8 DeviceSpeed,
650 IN UINTN MaximumPacketLength,
651 IN EFI_USB_DEVICE_REQUEST *Request,
652 IN EFI_USB_DATA_DIRECTION TransferDirection,
653 IN OUT VOID *Data,
654 IN OUT UINTN *DataLength,
655 IN UINTN TimeOut,
656 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
657 OUT UINT32 *TransferResult
658 )
659 {
660 USB2_HC_DEV *Ehc;
661 URB *Urb;
662 EFI_TPL OldTpl;
663 UINT8 Endpoint;
664 EFI_STATUS Status;
665
666 //
667 // Validate parameters
668 //
669 if ((Request == NULL) || (TransferResult == NULL)) {
670 return EFI_INVALID_PARAMETER;
671 }
672
673 if ((TransferDirection != EfiUsbDataIn) &&
674 (TransferDirection != EfiUsbDataOut) &&
675 (TransferDirection != EfiUsbNoData)) {
676 return EFI_INVALID_PARAMETER;
677 }
678
679 if ((TransferDirection == EfiUsbNoData) &&
680 ((Data != NULL) || (*DataLength != 0))) {
681 return EFI_INVALID_PARAMETER;
682 }
683
684 if ((TransferDirection != EfiUsbNoData) &&
685 ((Data == NULL) || (*DataLength == 0))) {
686 return EFI_INVALID_PARAMETER;
687 }
688
689 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&
690 (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {
691 return EFI_INVALID_PARAMETER;
692 }
693
694 if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {
695 return EFI_INVALID_PARAMETER;
696 }
697
698 OldTpl = gBS->RaiseTPL (EHC_TPL);
699 Ehc = EHC_FROM_THIS (This);
700
701 Status = EFI_DEVICE_ERROR;
702 *TransferResult = EFI_USB_ERR_SYSTEM;
703
704 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
705 DEBUG ((EFI_D_ERROR, "EhcControlTransfer: HC halted at entrance\n"));
706
707 EhcAckAllInterrupt (Ehc);
708 goto ON_EXIT;
709 }
710
711 EhcAckAllInterrupt (Ehc);
712
713 //
714 // Create a new URB, insert it into the asynchronous
715 // schedule list, then poll the execution status.
716 //
717 //
718 // Encode the direction in address, although default control
719 // endpoint is bidirectional. EhcCreateUrb expects this
720 // combination of Ep addr and its direction.
721 //
722 Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
723 Urb = EhcCreateUrb (
724 Ehc,
725 DeviceAddress,
726 Endpoint,
727 DeviceSpeed,
728 0,
729 MaximumPacketLength,
730 Translator,
731 EHC_CTRL_TRANSFER,
732 Request,
733 Data,
734 *DataLength,
735 NULL,
736 NULL,
737 1
738 );
739
740 if (Urb == NULL) {
741 DEBUG ((EFI_D_ERROR, "EhcControlTransfer: failed to create URB"));
742
743 Status = EFI_OUT_OF_RESOURCES;
744 goto ON_EXIT;
745 }
746
747 EhcLinkQhToAsync (Ehc, Urb->Qh);
748 Status = EhcExecTransfer (Ehc, Urb, TimeOut);
749 EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
750
751 //
752 // Get the status from URB. The result is updated in EhcCheckUrbResult
753 // which is called by EhcExecTransfer
754 //
755 *TransferResult = Urb->Result;
756 *DataLength = Urb->Completed;
757
758 if (*TransferResult == EFI_USB_NOERROR) {
759 Status = EFI_SUCCESS;
760 }
761
762 EhcAckAllInterrupt (Ehc);
763 EhcFreeUrb (Ehc, Urb);
764
765 ON_EXIT:
766 Ehc->PciIo->Flush (Ehc->PciIo);
767 gBS->RestoreTPL (OldTpl);
768
769 if (EFI_ERROR (Status)) {
770 DEBUG ((EFI_D_ERROR, "EhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
771 }
772
773 return Status;
774 }
775
776
777 /**
778 Submits bulk transfer to a bulk endpoint of a USB device.
779
780 @param This This EFI_USB2_HC_PROTOCOL instance.
781 @param DeviceAddress Target device address.
782 @param EndPointAddress Endpoint number and its direction in bit 7.
783 @param DeviceSpeed Device speed, Low speed device doesn't support bulk
784 transfer.
785 @param MaximumPacketLength Maximum packet size the endpoint is capable of
786 sending or receiving.
787 @param DataBuffersNumber Number of data buffers prepared for the transfer.
788 @param Data Array of pointers to the buffers of data to transmit
789 from or receive into.
790 @param DataLength The lenght of the data buffer.
791 @param DataToggle On input, the initial data toggle for the transfer;
792 On output, it is updated to to next data toggle to
793 use of the subsequent bulk transfer.
794 @param TimeOut Indicates the maximum time, in millisecond, which
795 the transfer is allowed to complete.
796 @param Translator A pointr to the transaction translator data.
797 @param TransferResult A pointer to the detailed result information of the
798 bulk transfer.
799
800 @retval EFI_SUCCESS The transfer was completed successfully.
801 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
802 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
803 @retval EFI_TIMEOUT The transfer failed due to timeout.
804 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
805
806 **/
807 EFI_STATUS
808 EFIAPI
809 EhcBulkTransfer (
810 IN EFI_USB2_HC_PROTOCOL *This,
811 IN UINT8 DeviceAddress,
812 IN UINT8 EndPointAddress,
813 IN UINT8 DeviceSpeed,
814 IN UINTN MaximumPacketLength,
815 IN UINT8 DataBuffersNumber,
816 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
817 IN OUT UINTN *DataLength,
818 IN OUT UINT8 *DataToggle,
819 IN UINTN TimeOut,
820 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
821 OUT UINT32 *TransferResult
822 )
823 {
824 USB2_HC_DEV *Ehc;
825 URB *Urb;
826 EFI_TPL OldTpl;
827 EFI_STATUS Status;
828
829 //
830 // Validate the parameters
831 //
832 if ((DataLength == NULL) || (*DataLength == 0) ||
833 (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {
834 return EFI_INVALID_PARAMETER;
835 }
836
837 if ((*DataToggle != 0) && (*DataToggle != 1)) {
838 return EFI_INVALID_PARAMETER;
839 }
840
841 if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
842 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
843 ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) {
844 return EFI_INVALID_PARAMETER;
845 }
846
847 OldTpl = gBS->RaiseTPL (EHC_TPL);
848 Ehc = EHC_FROM_THIS (This);
849
850 *TransferResult = EFI_USB_ERR_SYSTEM;
851 Status = EFI_DEVICE_ERROR;
852
853 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
854 DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: HC is halted\n"));
855
856 EhcAckAllInterrupt (Ehc);
857 goto ON_EXIT;
858 }
859
860 EhcAckAllInterrupt (Ehc);
861
862 //
863 // Create a new URB, insert it into the asynchronous
864 // schedule list, then poll the execution status.
865 //
866 Urb = EhcCreateUrb (
867 Ehc,
868 DeviceAddress,
869 EndPointAddress,
870 DeviceSpeed,
871 *DataToggle,
872 MaximumPacketLength,
873 Translator,
874 EHC_BULK_TRANSFER,
875 NULL,
876 Data[0],
877 *DataLength,
878 NULL,
879 NULL,
880 1
881 );
882
883 if (Urb == NULL) {
884 DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: failed to create URB\n"));
885
886 Status = EFI_OUT_OF_RESOURCES;
887 goto ON_EXIT;
888 }
889
890 EhcLinkQhToAsync (Ehc, Urb->Qh);
891 Status = EhcExecTransfer (Ehc, Urb, TimeOut);
892 EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
893
894 *TransferResult = Urb->Result;
895 *DataLength = Urb->Completed;
896 *DataToggle = Urb->DataToggle;
897
898 if (*TransferResult == EFI_USB_NOERROR) {
899 Status = EFI_SUCCESS;
900 }
901
902 EhcAckAllInterrupt (Ehc);
903 EhcFreeUrb (Ehc, Urb);
904
905 ON_EXIT:
906 Ehc->PciIo->Flush (Ehc->PciIo);
907 gBS->RestoreTPL (OldTpl);
908
909 if (EFI_ERROR (Status)) {
910 DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
911 }
912
913 return Status;
914 }
915
916
917 /**
918 Submits an asynchronous interrupt transfer to an
919 interrupt endpoint of a USB device.
920
921 @param This This EFI_USB2_HC_PROTOCOL instance.
922 @param DeviceAddress Target device address.
923 @param EndPointAddress Endpoint number and its direction encoded in bit 7
924 @param DeviceSpeed Indicates device speed.
925 @param MaximumPacketLength Maximum packet size the target endpoint is capable
926 @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt
927 transfer If FALSE, to remove the specified
928 asynchronous interrupt.
929 @param DataToggle On input, the initial data toggle to use; on output,
930 it is updated to indicate the next data toggle.
931 @param PollingInterval The he interval, in milliseconds, that the transfer
932 is polled.
933 @param DataLength The length of data to receive at the rate specified
934 by PollingInterval.
935 @param Translator Transaction translator to use.
936 @param CallBackFunction Function to call at the rate specified by
937 PollingInterval.
938 @param Context Context to CallBackFunction.
939
940 @retval EFI_SUCCESS The request has been successfully submitted or canceled.
941 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
942 @retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources.
943 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
944
945 **/
946 EFI_STATUS
947 EFIAPI
948 EhcAsyncInterruptTransfer (
949 IN EFI_USB2_HC_PROTOCOL * This,
950 IN UINT8 DeviceAddress,
951 IN UINT8 EndPointAddress,
952 IN UINT8 DeviceSpeed,
953 IN UINTN MaximumPacketLength,
954 IN BOOLEAN IsNewTransfer,
955 IN OUT UINT8 *DataToggle,
956 IN UINTN PollingInterval,
957 IN UINTN DataLength,
958 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,
959 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
960 IN VOID *Context OPTIONAL
961 )
962 {
963 USB2_HC_DEV *Ehc;
964 URB *Urb;
965 EFI_TPL OldTpl;
966 EFI_STATUS Status;
967 UINT8 *Data;
968
969 //
970 // Validate parameters
971 //
972 if (!EHCI_IS_DATAIN (EndPointAddress)) {
973 return EFI_INVALID_PARAMETER;
974 }
975
976 if (IsNewTransfer) {
977 if (DataLength == 0) {
978 return EFI_INVALID_PARAMETER;
979 }
980
981 if ((*DataToggle != 1) && (*DataToggle != 0)) {
982 return EFI_INVALID_PARAMETER;
983 }
984
985 if ((PollingInterval > 255) || (PollingInterval < 1)) {
986 return EFI_INVALID_PARAMETER;
987 }
988 }
989
990 OldTpl = gBS->RaiseTPL (EHC_TPL);
991 Ehc = EHC_FROM_THIS (This);
992
993 //
994 // Delete Async interrupt transfer request. DataToggle will return
995 // the next data toggle to use.
996 //
997 if (!IsNewTransfer) {
998 Status = EhciDelAsyncIntTransfer (Ehc, DeviceAddress, EndPointAddress, DataToggle);
999
1000 DEBUG ((EFI_D_INFO, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status));
1001 goto ON_EXIT;
1002 }
1003
1004 Status = EFI_SUCCESS;
1005
1006 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
1007 DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: HC is halt\n"));
1008 EhcAckAllInterrupt (Ehc);
1009
1010 Status = EFI_DEVICE_ERROR;
1011 goto ON_EXIT;
1012 }
1013
1014 EhcAckAllInterrupt (Ehc);
1015
1016 Data = AllocatePool (DataLength);
1017
1018 if (Data == NULL) {
1019 DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: failed to allocate buffer\n"));
1020
1021 Status = EFI_OUT_OF_RESOURCES;
1022 goto ON_EXIT;
1023 }
1024
1025 Urb = EhcCreateUrb (
1026 Ehc,
1027 DeviceAddress,
1028 EndPointAddress,
1029 DeviceSpeed,
1030 *DataToggle,
1031 MaximumPacketLength,
1032 Translator,
1033 EHC_INT_TRANSFER_ASYNC,
1034 NULL,
1035 Data,
1036 DataLength,
1037 CallBackFunction,
1038 Context,
1039 PollingInterval
1040 );
1041
1042 if (Urb == NULL) {
1043 DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: failed to create URB\n"));
1044
1045 gBS->FreePool (Data);
1046 Status = EFI_OUT_OF_RESOURCES;
1047 goto ON_EXIT;
1048 }
1049
1050 //
1051 // New asynchronous transfer must inserted to the head.
1052 // Check the comments in EhcMoniteAsyncRequests
1053 //
1054 EhcLinkQhToPeriod (Ehc, Urb->Qh);
1055 InsertHeadList (&Ehc->AsyncIntTransfers, &Urb->UrbList);
1056
1057 ON_EXIT:
1058 Ehc->PciIo->Flush (Ehc->PciIo);
1059 gBS->RestoreTPL (OldTpl);
1060
1061 return Status;
1062 }
1063
1064
1065 /**
1066 Submits synchronous interrupt transfer to an interrupt endpoint
1067 of a USB device.
1068
1069 @param This This EFI_USB2_HC_PROTOCOL instance.
1070 @param DeviceAddress Target device address.
1071 @param EndPointAddress Endpoint number and its direction encoded in bit 7
1072 @param DeviceSpeed Indicates device speed.
1073 @param MaximumPacketLength Maximum packet size the target endpoint is capable
1074 of sending or receiving.
1075 @param Data Buffer of data that will be transmitted to USB
1076 device or received from USB device.
1077 @param DataLength On input, the size, in bytes, of the data buffer; On
1078 output, the number of bytes transferred.
1079 @param DataToggle On input, the initial data toggle to use; on output,
1080 it is updated to indicate the next data toggle.
1081 @param TimeOut Maximum time, in second, to complete.
1082 @param Translator Transaction translator to use.
1083 @param TransferResult Variable to receive the transfer result.
1084
1085 @return EFI_SUCCESS The transfer was completed successfully.
1086 @return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
1087 @return EFI_INVALID_PARAMETER Some parameters are invalid.
1088 @return EFI_TIMEOUT The transfer failed due to timeout.
1089 @return EFI_DEVICE_ERROR The failed due to host controller or device error
1090
1091 **/
1092 EFI_STATUS
1093 EFIAPI
1094 EhcSyncInterruptTransfer (
1095 IN EFI_USB2_HC_PROTOCOL *This,
1096 IN UINT8 DeviceAddress,
1097 IN UINT8 EndPointAddress,
1098 IN UINT8 DeviceSpeed,
1099 IN UINTN MaximumPacketLength,
1100 IN OUT VOID *Data,
1101 IN OUT UINTN *DataLength,
1102 IN OUT UINT8 *DataToggle,
1103 IN UINTN TimeOut,
1104 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
1105 OUT UINT32 *TransferResult
1106 )
1107 {
1108 USB2_HC_DEV *Ehc;
1109 EFI_TPL OldTpl;
1110 URB *Urb;
1111 EFI_STATUS Status;
1112
1113 //
1114 // Validates parameters
1115 //
1116 if ((DataLength == NULL) || (*DataLength == 0) ||
1117 (Data == NULL) || (TransferResult == NULL)) {
1118 return EFI_INVALID_PARAMETER;
1119 }
1120
1121 if (!EHCI_IS_DATAIN (EndPointAddress)) {
1122 return EFI_INVALID_PARAMETER;
1123 }
1124
1125 if ((*DataToggle != 1) && (*DataToggle != 0)) {
1126 return EFI_INVALID_PARAMETER;
1127 }
1128
1129 if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) ||
1130 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
1131 ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) {
1132 return EFI_INVALID_PARAMETER;
1133 }
1134
1135 OldTpl = gBS->RaiseTPL (EHC_TPL);
1136 Ehc = EHC_FROM_THIS (This);
1137
1138 *TransferResult = EFI_USB_ERR_SYSTEM;
1139 Status = EFI_DEVICE_ERROR;
1140
1141 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
1142 DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));
1143
1144 EhcAckAllInterrupt (Ehc);
1145 goto ON_EXIT;
1146 }
1147
1148 EhcAckAllInterrupt (Ehc);
1149
1150 Urb = EhcCreateUrb (
1151 Ehc,
1152 DeviceAddress,
1153 EndPointAddress,
1154 DeviceSpeed,
1155 *DataToggle,
1156 MaximumPacketLength,
1157 Translator,
1158 EHC_INT_TRANSFER_SYNC,
1159 NULL,
1160 Data,
1161 *DataLength,
1162 NULL,
1163 NULL,
1164 1
1165 );
1166
1167 if (Urb == NULL) {
1168 DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: failed to create URB\n"));
1169
1170 Status = EFI_OUT_OF_RESOURCES;
1171 goto ON_EXIT;
1172 }
1173
1174 EhcLinkQhToPeriod (Ehc, Urb->Qh);
1175 Status = EhcExecTransfer (Ehc, Urb, TimeOut);
1176 EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);
1177
1178 *TransferResult = Urb->Result;
1179 *DataLength = Urb->Completed;
1180 *DataToggle = Urb->DataToggle;
1181
1182 if (*TransferResult == EFI_USB_NOERROR) {
1183 Status = EFI_SUCCESS;
1184 }
1185
1186 ON_EXIT:
1187 Ehc->PciIo->Flush (Ehc->PciIo);
1188 gBS->RestoreTPL (OldTpl);
1189
1190 if (EFI_ERROR (Status)) {
1191 DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
1192 }
1193
1194 return Status;
1195 }
1196
1197
1198 /**
1199 Submits isochronous transfer to a target USB device.
1200
1201 @param This This EFI_USB2_HC_PROTOCOL instance.
1202 @param DeviceAddress Target device address.
1203 @param EndPointAddress End point address with its direction.
1204 @param DeviceSpeed Device speed, Low speed device doesn't support this
1205 type.
1206 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1207 sending or receiving.
1208 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1209 @param Data Array of pointers to the buffers of data that will
1210 be transmitted to USB device or received from USB
1211 device.
1212 @param DataLength The size, in bytes, of the data buffer.
1213 @param Translator Transaction translator to use.
1214 @param TransferResult Variable to receive the transfer result.
1215
1216 @return EFI_UNSUPPORTED Isochronous transfer is unsupported.
1217
1218 **/
1219 EFI_STATUS
1220 EFIAPI
1221 EhcIsochronousTransfer (
1222 IN EFI_USB2_HC_PROTOCOL *This,
1223 IN UINT8 DeviceAddress,
1224 IN UINT8 EndPointAddress,
1225 IN UINT8 DeviceSpeed,
1226 IN UINTN MaximumPacketLength,
1227 IN UINT8 DataBuffersNumber,
1228 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
1229 IN UINTN DataLength,
1230 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
1231 OUT UINT32 *TransferResult
1232 )
1233 {
1234 return EFI_UNSUPPORTED;
1235 }
1236
1237
1238 /**
1239 Submits Async isochronous transfer to a target USB device.
1240
1241 @param This This EFI_USB2_HC_PROTOCOL instance.
1242 @param DeviceAddress Target device address.
1243 @param EndPointAddress End point address with its direction.
1244 @param DeviceSpeed Device speed, Low speed device doesn't support this
1245 type.
1246 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1247 sending or receiving.
1248 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1249 @param Data Array of pointers to the buffers of data that will
1250 be transmitted to USB device or received from USB
1251 device.
1252 @param DataLength The size, in bytes, of the data buffer.
1253 @param Translator Transaction translator to use.
1254 @param IsochronousCallBack Function to be called when the transfer complete.
1255 @param Context Context passed to the call back function as
1256 parameter.
1257
1258 @return EFI_UNSUPPORTED Isochronous transfer isn't supported.
1259
1260 **/
1261 EFI_STATUS
1262 EFIAPI
1263 EhcAsyncIsochronousTransfer (
1264 IN EFI_USB2_HC_PROTOCOL *This,
1265 IN UINT8 DeviceAddress,
1266 IN UINT8 EndPointAddress,
1267 IN UINT8 DeviceSpeed,
1268 IN UINTN MaximumPacketLength,
1269 IN UINT8 DataBuffersNumber,
1270 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
1271 IN UINTN DataLength,
1272 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
1273 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
1274 IN VOID *Context
1275 )
1276 {
1277 return EFI_UNSUPPORTED;
1278 }
1279
1280 /**
1281 Entry point for EFI drivers.
1282
1283 @param ImageHandle EFI_HANDLE.
1284 @param SystemTable EFI_SYSTEM_TABLE.
1285
1286 @return EFI_SUCCESS Success.
1287 EFI_DEVICE_ERROR Fail.
1288
1289 **/
1290 EFI_STATUS
1291 EFIAPI
1292 EhcDriverEntryPoint (
1293 IN EFI_HANDLE ImageHandle,
1294 IN EFI_SYSTEM_TABLE *SystemTable
1295 )
1296 {
1297 return EfiLibInstallDriverBindingComponentName2 (
1298 ImageHandle,
1299 SystemTable,
1300 &gEhciDriverBinding,
1301 ImageHandle,
1302 &gEhciComponentName,
1303 &gEhciComponentName2
1304 );
1305 }
1306
1307
1308 /**
1309 Test to see if this driver supports ControllerHandle. Any
1310 ControllerHandle that has Usb2HcProtocol installed will
1311 be supported.
1312
1313 @param This Protocol instance pointer.
1314 @param Controller Handle of device to test.
1315 @param RemainingDevicePath Not used.
1316
1317 @return EFI_SUCCESS This driver supports this device.
1318 @return EFI_UNSUPPORTED This driver does not support this device.
1319
1320 **/
1321 EFI_STATUS
1322 EFIAPI
1323 EhcDriverBindingSupported (
1324 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1325 IN EFI_HANDLE Controller,
1326 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1327 )
1328 {
1329 EFI_STATUS Status;
1330 EFI_PCI_IO_PROTOCOL *PciIo;
1331 USB_CLASSC UsbClassCReg;
1332
1333 //
1334 // Test whether there is PCI IO Protocol attached on the controller handle.
1335 //
1336 Status = gBS->OpenProtocol (
1337 Controller,
1338 &gEfiPciIoProtocolGuid,
1339 (VOID **) &PciIo,
1340 This->DriverBindingHandle,
1341 Controller,
1342 EFI_OPEN_PROTOCOL_BY_DRIVER
1343 );
1344
1345 if (EFI_ERROR (Status)) {
1346 return EFI_UNSUPPORTED;
1347 }
1348
1349 Status = PciIo->Pci.Read (
1350 PciIo,
1351 EfiPciIoWidthUint8,
1352 PCI_CLASSCODE_OFFSET,
1353 sizeof (USB_CLASSC) / sizeof (UINT8),
1354 &UsbClassCReg
1355 );
1356
1357 if (EFI_ERROR (Status)) {
1358 Status = EFI_UNSUPPORTED;
1359 goto ON_EXIT;
1360 }
1361
1362 //
1363 // Test whether the controller belongs to Ehci type
1364 //
1365 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB)
1366 || ((UsbClassCReg.ProgInterface != PCI_IF_EHCI) && (UsbClassCReg.ProgInterface !=PCI_IF_UHCI))) {
1367
1368 Status = EFI_UNSUPPORTED;
1369 }
1370
1371 ON_EXIT:
1372 gBS->CloseProtocol (
1373 Controller,
1374 &gEfiPciIoProtocolGuid,
1375 This->DriverBindingHandle,
1376 Controller
1377 );
1378
1379 return Status;
1380 }
1381
1382
1383 /**
1384 Create and initialize a USB2_HC_DEV.
1385
1386 @param PciIo The PciIo on this device.
1387 @param OriginalPciAttributes Original PCI attributes.
1388
1389 @return The allocated and initialized USB2_HC_DEV structure if created,
1390 otherwise NULL.
1391
1392 **/
1393 USB2_HC_DEV *
1394 EhcCreateUsb2Hc (
1395 IN EFI_PCI_IO_PROTOCOL *PciIo,
1396 IN UINT64 OriginalPciAttributes
1397 )
1398 {
1399 USB2_HC_DEV *Ehc;
1400 EFI_STATUS Status;
1401
1402 Ehc = AllocateZeroPool (sizeof (USB2_HC_DEV));
1403
1404 if (Ehc == NULL) {
1405 return NULL;
1406 }
1407
1408 //
1409 // Init EFI_USB2_HC_PROTOCOL interface and private data structure
1410 //
1411 Ehc->Signature = USB2_HC_DEV_SIGNATURE;
1412
1413 Ehc->Usb2Hc.GetCapability = EhcGetCapability;
1414 Ehc->Usb2Hc.Reset = EhcReset;
1415 Ehc->Usb2Hc.GetState = EhcGetState;
1416 Ehc->Usb2Hc.SetState = EhcSetState;
1417 Ehc->Usb2Hc.ControlTransfer = EhcControlTransfer;
1418 Ehc->Usb2Hc.BulkTransfer = EhcBulkTransfer;
1419 Ehc->Usb2Hc.AsyncInterruptTransfer = EhcAsyncInterruptTransfer;
1420 Ehc->Usb2Hc.SyncInterruptTransfer = EhcSyncInterruptTransfer;
1421 Ehc->Usb2Hc.IsochronousTransfer = EhcIsochronousTransfer;
1422 Ehc->Usb2Hc.AsyncIsochronousTransfer = EhcAsyncIsochronousTransfer;
1423 Ehc->Usb2Hc.GetRootHubPortStatus = EhcGetRootHubPortStatus;
1424 Ehc->Usb2Hc.SetRootHubPortFeature = EhcSetRootHubPortFeature;
1425 Ehc->Usb2Hc.ClearRootHubPortFeature = EhcClearRootHubPortFeature;
1426 Ehc->Usb2Hc.MajorRevision = 0x2;
1427 Ehc->Usb2Hc.MinorRevision = 0x0;
1428
1429 Ehc->PciIo = PciIo;
1430 Ehc->OriginalPciAttributes = OriginalPciAttributes;
1431
1432 InitializeListHead (&Ehc->AsyncIntTransfers);
1433
1434 Ehc->HcStructParams = EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET);
1435 Ehc->HcCapParams = EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET);
1436 Ehc->CapLen = EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET) & 0x0FF;
1437
1438 DEBUG ((EFI_D_INFO, "EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen));
1439
1440 //
1441 // EHCI Controllers with a CapLen of 0 are ignored.
1442 //
1443 if (Ehc->CapLen == 0) {
1444 gBS->FreePool (Ehc);
1445 return NULL;
1446 }
1447
1448 //
1449 // Create AsyncRequest Polling Timer
1450 //
1451 Status = gBS->CreateEvent (
1452 EVT_TIMER | EVT_NOTIFY_SIGNAL,
1453 TPL_CALLBACK,
1454 EhcMonitorAsyncRequests,
1455 Ehc,
1456 &Ehc->PollTimer
1457 );
1458
1459 if (EFI_ERROR (Status)) {
1460 gBS->FreePool (Ehc);
1461 return NULL;
1462 }
1463
1464 return Ehc;
1465 }
1466
1467 /**
1468 One notified function to stop the Host Controller when gBS->ExitBootServices() called.
1469
1470 @param Event Pointer to this event
1471 @param Context Event hanlder private data
1472
1473 **/
1474 VOID
1475 EFIAPI
1476 EhcExitBootService (
1477 EFI_EVENT Event,
1478 VOID *Context
1479 )
1480
1481 {
1482 USB2_HC_DEV *Ehc;
1483
1484 Ehc = (USB2_HC_DEV *) Context;
1485
1486 //
1487 // Reset the Host Controller
1488 //
1489 EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
1490 }
1491
1492
1493 /**
1494 Starting the Usb EHCI Driver.
1495
1496 @param This Protocol instance pointer.
1497 @param Controller Handle of device to test.
1498 @param RemainingDevicePath Not used.
1499
1500 @return EFI_SUCCESS supports this device.
1501 @return EFI_UNSUPPORTED do not support this device.
1502 @return EFI_DEVICE_ERROR cannot be started due to device Error.
1503 @return EFI_OUT_OF_RESOURCES cannot allocate resources.
1504
1505 **/
1506 EFI_STATUS
1507 EFIAPI
1508 EhcDriverBindingStart (
1509 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1510 IN EFI_HANDLE Controller,
1511 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1512 )
1513 {
1514 EFI_STATUS Status;
1515 USB2_HC_DEV *Ehc;
1516 EFI_PCI_IO_PROTOCOL *PciIo;
1517 EFI_PCI_IO_PROTOCOL *Instance;
1518 UINT64 Supports;
1519 UINT64 OriginalPciAttributes;
1520 BOOLEAN PciAttributesSaved;
1521 USB_CLASSC UsbClassCReg;
1522 EFI_HANDLE *HandleBuffer;
1523 UINTN NumberOfHandles;
1524 UINTN Index;
1525 UINTN UhciSegmentNumber;
1526 UINTN UhciBusNumber;
1527 UINTN UhciDeviceNumber;
1528 UINTN UhciFunctionNumber;
1529 UINTN EhciSegmentNumber;
1530 UINTN EhciBusNumber;
1531 UINTN EhciDeviceNumber;
1532 UINTN EhciFunctionNumber;
1533
1534 //
1535 // Open the PciIo Protocol, then enable the USB host controller
1536 //
1537 Status = gBS->OpenProtocol (
1538 Controller,
1539 &gEfiPciIoProtocolGuid,
1540 (VOID **) &PciIo,
1541 This->DriverBindingHandle,
1542 Controller,
1543 EFI_OPEN_PROTOCOL_BY_DRIVER
1544 );
1545
1546 if (EFI_ERROR (Status)) {
1547 return Status;
1548 }
1549
1550 PciAttributesSaved = FALSE;
1551 //
1552 // Save original PCI attributes
1553 //
1554 Status = PciIo->Attributes (
1555 PciIo,
1556 EfiPciIoAttributeOperationGet,
1557 0,
1558 &OriginalPciAttributes
1559 );
1560
1561 if (EFI_ERROR (Status)) {
1562 goto CLOSE_PCIIO;
1563 }
1564 PciAttributesSaved = TRUE;
1565
1566 Status = PciIo->Attributes (
1567 PciIo,
1568 EfiPciIoAttributeOperationSupported,
1569 0,
1570 &Supports
1571 );
1572 if (!EFI_ERROR (Status)) {
1573 Supports &= EFI_PCI_DEVICE_ENABLE;
1574 Status = PciIo->Attributes (
1575 PciIo,
1576 EfiPciIoAttributeOperationEnable,
1577 Supports,
1578 NULL
1579 );
1580 }
1581
1582 if (EFI_ERROR (Status)) {
1583 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to enable controller\n"));
1584 goto CLOSE_PCIIO;
1585 }
1586
1587 //
1588 // Get the Pci device class code.
1589 //
1590 Status = PciIo->Pci.Read (
1591 PciIo,
1592 EfiPciIoWidthUint8,
1593 PCI_CLASSCODE_OFFSET,
1594 sizeof (USB_CLASSC) / sizeof (UINT8),
1595 &UsbClassCReg
1596 );
1597
1598 if (EFI_ERROR (Status)) {
1599 Status = EFI_UNSUPPORTED;
1600 goto CLOSE_PCIIO;
1601 }
1602 //
1603 // determine if the device is UHCI host controller or not. If yes, then find out the
1604 // companion usb ehci host controller and force EHCI driver get attached to it before
1605 // UHCI driver attaches to UHCI host controller.
1606 //
1607 if ((UsbClassCReg.ProgInterface == PCI_IF_UHCI) &&
1608 (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
1609 (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
1610 Status = PciIo->GetLocation (
1611 PciIo,
1612 &UhciSegmentNumber,
1613 &UhciBusNumber,
1614 &UhciDeviceNumber,
1615 &UhciFunctionNumber
1616 );
1617 if (EFI_ERROR (Status)) {
1618 goto CLOSE_PCIIO;
1619 }
1620
1621 Status = gBS->LocateHandleBuffer (
1622 ByProtocol,
1623 &gEfiPciIoProtocolGuid,
1624 NULL,
1625 &NumberOfHandles,
1626 &HandleBuffer
1627 );
1628 if (EFI_ERROR (Status)) {
1629 goto CLOSE_PCIIO;
1630 }
1631
1632 for (Index = 0; Index < NumberOfHandles; Index++) {
1633 //
1634 // Get the device path on this handle
1635 //
1636 Status = gBS->HandleProtocol (
1637 HandleBuffer[Index],
1638 &gEfiPciIoProtocolGuid,
1639 (VOID **)&Instance
1640 );
1641 ASSERT_EFI_ERROR (Status);
1642
1643 Status = Instance->Pci.Read (
1644 Instance,
1645 EfiPciIoWidthUint8,
1646 PCI_CLASSCODE_OFFSET,
1647 sizeof (USB_CLASSC) / sizeof (UINT8),
1648 &UsbClassCReg
1649 );
1650
1651 if (EFI_ERROR (Status)) {
1652 Status = EFI_UNSUPPORTED;
1653 goto CLOSE_PCIIO;
1654 }
1655
1656 if ((UsbClassCReg.ProgInterface == PCI_IF_EHCI) &&
1657 (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
1658 (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
1659 Status = Instance->GetLocation (
1660 Instance,
1661 &EhciSegmentNumber,
1662 &EhciBusNumber,
1663 &EhciDeviceNumber,
1664 &EhciFunctionNumber
1665 );
1666 if (EFI_ERROR (Status)) {
1667 goto CLOSE_PCIIO;
1668 }
1669 //
1670 // Currently, the judgment on the companion usb host controller is through the
1671 // same bus number, which may vary on different platform.
1672 //
1673 if (EhciBusNumber == UhciBusNumber) {
1674 gBS->CloseProtocol (
1675 Controller,
1676 &gEfiPciIoProtocolGuid,
1677 This->DriverBindingHandle,
1678 Controller
1679 );
1680 EhcDriverBindingStart(This, HandleBuffer[Index], NULL);
1681 }
1682 }
1683 }
1684 Status = EFI_NOT_FOUND;
1685 goto CLOSE_PCIIO;
1686 }
1687
1688 //
1689 // Create then install USB2_HC_PROTOCOL
1690 //
1691 Ehc = EhcCreateUsb2Hc (PciIo, OriginalPciAttributes);
1692
1693 if (Ehc == NULL) {
1694 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to create USB2_HC\n"));
1695
1696 Status = EFI_OUT_OF_RESOURCES;
1697 goto CLOSE_PCIIO;
1698 }
1699
1700 Status = gBS->InstallProtocolInterface (
1701 &Controller,
1702 &gEfiUsb2HcProtocolGuid,
1703 EFI_NATIVE_INTERFACE,
1704 &Ehc->Usb2Hc
1705 );
1706
1707 if (EFI_ERROR (Status)) {
1708 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
1709 goto FREE_POOL;
1710 }
1711
1712 //
1713 // Robustnesss improvement such as for Duet platform
1714 // Default is not required.
1715 //
1716 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
1717 EhcClearLegacySupport (Ehc);
1718 }
1719 EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
1720
1721 Status = EhcInitHC (Ehc);
1722
1723 if (EFI_ERROR (Status)) {
1724 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to init host controller\n"));
1725 goto UNINSTALL_USBHC;
1726 }
1727
1728 //
1729 // Start the asynchronous interrupt monitor
1730 //
1731 Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL);
1732
1733 if (EFI_ERROR (Status)) {
1734 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
1735
1736 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
1737 goto UNINSTALL_USBHC;
1738 }
1739
1740 //
1741 // Create event to stop the HC when exit boot service.
1742 //
1743 Status = gBS->CreateEventEx (
1744 EVT_NOTIFY_SIGNAL,
1745 TPL_NOTIFY,
1746 EhcExitBootService,
1747 Ehc,
1748 &gEfiEventExitBootServicesGuid,
1749 &Ehc->ExitBootServiceEvent
1750 );
1751 if (EFI_ERROR (Status)) {
1752 goto UNINSTALL_USBHC;
1753 }
1754
1755 //
1756 // Install the component name protocol, don't fail the start
1757 // because of something for display.
1758 //
1759 AddUnicodeString2 (
1760 "eng",
1761 gEhciComponentName.SupportedLanguages,
1762 &Ehc->ControllerNameTable,
1763 L"Enhanced Host Controller (USB 2.0)",
1764 TRUE
1765 );
1766 AddUnicodeString2 (
1767 "en",
1768 gEhciComponentName2.SupportedLanguages,
1769 &Ehc->ControllerNameTable,
1770 L"Enhanced Host Controller (USB 2.0)",
1771 FALSE
1772 );
1773
1774
1775 DEBUG ((EFI_D_INFO, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller));
1776 return EFI_SUCCESS;
1777
1778 UNINSTALL_USBHC:
1779 gBS->UninstallProtocolInterface (
1780 Controller,
1781 &gEfiUsb2HcProtocolGuid,
1782 &Ehc->Usb2Hc
1783 );
1784
1785 FREE_POOL:
1786 EhcFreeSched (Ehc);
1787 gBS->CloseEvent (Ehc->PollTimer);
1788 gBS->FreePool (Ehc);
1789
1790 CLOSE_PCIIO:
1791 if (PciAttributesSaved) {
1792 //
1793 // Restore original PCI attributes
1794 //
1795 PciIo->Attributes (
1796 PciIo,
1797 EfiPciIoAttributeOperationSet,
1798 OriginalPciAttributes,
1799 NULL
1800 );
1801 }
1802
1803 gBS->CloseProtocol (
1804 Controller,
1805 &gEfiPciIoProtocolGuid,
1806 This->DriverBindingHandle,
1807 Controller
1808 );
1809
1810 return Status;
1811 }
1812
1813
1814 /**
1815 Stop this driver on ControllerHandle. Support stoping any child handles
1816 created by this driver.
1817
1818 @param This Protocol instance pointer.
1819 @param Controller Handle of device to stop driver on.
1820 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
1821 @param ChildHandleBuffer List of handles for the children we need to stop.
1822
1823 @return EFI_SUCCESS Success.
1824 @return EFI_DEVICE_ERROR Fail.
1825
1826 **/
1827 EFI_STATUS
1828 EFIAPI
1829 EhcDriverBindingStop (
1830 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1831 IN EFI_HANDLE Controller,
1832 IN UINTN NumberOfChildren,
1833 IN EFI_HANDLE *ChildHandleBuffer
1834 )
1835 {
1836 EFI_STATUS Status;
1837 EFI_USB2_HC_PROTOCOL *Usb2Hc;
1838 EFI_PCI_IO_PROTOCOL *PciIo;
1839 USB2_HC_DEV *Ehc;
1840
1841 //
1842 // Test whether the Controller handler passed in is a valid
1843 // Usb controller handle that should be supported, if not,
1844 // return the error status directly
1845 //
1846 Status = gBS->OpenProtocol (
1847 Controller,
1848 &gEfiUsb2HcProtocolGuid,
1849 (VOID **) &Usb2Hc,
1850 This->DriverBindingHandle,
1851 Controller,
1852 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1853 );
1854
1855 if (EFI_ERROR (Status)) {
1856 return Status;
1857 }
1858
1859 Ehc = EHC_FROM_THIS (Usb2Hc);
1860 PciIo = Ehc->PciIo;
1861
1862 //
1863 // Stop AsyncRequest Polling timer then stop the EHCI driver
1864 // and uninstall the EHCI protocl.
1865 //
1866 gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL);
1867 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
1868
1869 Status = gBS->UninstallProtocolInterface (
1870 Controller,
1871 &gEfiUsb2HcProtocolGuid,
1872 Usb2Hc
1873 );
1874
1875 if (EFI_ERROR (Status)) {
1876 return Status;
1877 }
1878
1879 if (Ehc->PollTimer != NULL) {
1880 gBS->CloseEvent (Ehc->PollTimer);
1881 }
1882
1883 if (Ehc->ExitBootServiceEvent != NULL) {
1884 gBS->CloseEvent (Ehc->ExitBootServiceEvent);
1885 }
1886
1887 EhcFreeSched (Ehc);
1888
1889 if (Ehc->ControllerNameTable != NULL) {
1890 FreeUnicodeStringTable (Ehc->ControllerNameTable);
1891 }
1892
1893 //
1894 // Disable routing of all ports to EHCI controller, so all ports are
1895 // routed back to the UHCI controller.
1896 //
1897 EhcClearOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
1898
1899 //
1900 // Restore original PCI attributes
1901 //
1902 PciIo->Attributes (
1903 PciIo,
1904 EfiPciIoAttributeOperationSet,
1905 Ehc->OriginalPciAttributes,
1906 NULL
1907 );
1908
1909 gBS->CloseProtocol (
1910 Controller,
1911 &gEfiPciIoProtocolGuid,
1912 This->DriverBindingHandle,
1913 Controller
1914 );
1915
1916 FreePool (Ehc);
1917
1918 return EFI_SUCCESS;
1919 }
1920