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