]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
code cleanup:
[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 0x30,
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 PCI_CLASSCODE_OFFSET,
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) || (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB)
1358 || ((UsbClassCReg.PI != PCI_IF_EHCI) && (UsbClassCReg.PI !=PCI_IF_UHCI))) {
1359
1360 Status = EFI_UNSUPPORTED;
1361 }
1362
1363 ON_EXIT:
1364 gBS->CloseProtocol (
1365 Controller,
1366 &gEfiPciIoProtocolGuid,
1367 This->DriverBindingHandle,
1368 Controller
1369 );
1370
1371 return Status;
1372 }
1373
1374
1375 /**
1376 Create and initialize a USB2_HC_DEV.
1377
1378 @param PciIo The PciIo on this device.
1379 @param OriginalPciAttributes Original PCI attributes.
1380
1381 @return The allocated and initialized USB2_HC_DEV structure if created,
1382 otherwise NULL.
1383
1384 **/
1385 USB2_HC_DEV *
1386 EhcCreateUsb2Hc (
1387 IN EFI_PCI_IO_PROTOCOL *PciIo,
1388 IN UINT64 OriginalPciAttributes
1389 )
1390 {
1391 USB2_HC_DEV *Ehc;
1392 EFI_STATUS Status;
1393
1394 Ehc = AllocateZeroPool (sizeof (USB2_HC_DEV));
1395
1396 if (Ehc == NULL) {
1397 return NULL;
1398 }
1399
1400 //
1401 // Init EFI_USB2_HC_PROTOCOL interface and private data structure
1402 //
1403 Ehc->Signature = USB2_HC_DEV_SIGNATURE;
1404
1405 Ehc->Usb2Hc.GetCapability = EhcGetCapability;
1406 Ehc->Usb2Hc.Reset = EhcReset;
1407 Ehc->Usb2Hc.GetState = EhcGetState;
1408 Ehc->Usb2Hc.SetState = EhcSetState;
1409 Ehc->Usb2Hc.ControlTransfer = EhcControlTransfer;
1410 Ehc->Usb2Hc.BulkTransfer = EhcBulkTransfer;
1411 Ehc->Usb2Hc.AsyncInterruptTransfer = EhcAsyncInterruptTransfer;
1412 Ehc->Usb2Hc.SyncInterruptTransfer = EhcSyncInterruptTransfer;
1413 Ehc->Usb2Hc.IsochronousTransfer = EhcIsochronousTransfer;
1414 Ehc->Usb2Hc.AsyncIsochronousTransfer = EhcAsyncIsochronousTransfer;
1415 Ehc->Usb2Hc.GetRootHubPortStatus = EhcGetRootHubPortStatus;
1416 Ehc->Usb2Hc.SetRootHubPortFeature = EhcSetRootHubPortFeature;
1417 Ehc->Usb2Hc.ClearRootHubPortFeature = EhcClearRootHubPortFeature;
1418 Ehc->Usb2Hc.MajorRevision = 0x2;
1419 Ehc->Usb2Hc.MinorRevision = 0x0;
1420
1421 Ehc->PciIo = PciIo;
1422 Ehc->OriginalPciAttributes = OriginalPciAttributes;
1423
1424 InitializeListHead (&Ehc->AsyncIntTransfers);
1425
1426 Ehc->HcStructParams = EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET);
1427 Ehc->HcCapParams = EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET);
1428 Ehc->CapLen = EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET) & 0x0FF;
1429
1430 DEBUG ((EFI_D_INFO, "EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen));
1431
1432 //
1433 // Create AsyncRequest Polling Timer
1434 //
1435 Status = gBS->CreateEvent (
1436 EVT_TIMER | EVT_NOTIFY_SIGNAL,
1437 TPL_CALLBACK,
1438 EhcMonitorAsyncRequests,
1439 Ehc,
1440 &Ehc->PollTimer
1441 );
1442
1443 if (EFI_ERROR (Status)) {
1444 gBS->FreePool (Ehc);
1445 return NULL;
1446 }
1447
1448 return Ehc;
1449 }
1450
1451 /**
1452 One notified function to stop the Host Controller when gBS->ExitBootServices() called.
1453
1454 @param Event Pointer to this event
1455 @param Context Event hanlder private data
1456
1457 **/
1458 VOID
1459 EFIAPI
1460 EhcExitBootService (
1461 EFI_EVENT Event,
1462 VOID *Context
1463 )
1464
1465 {
1466 USB2_HC_DEV *Ehc;
1467
1468 Ehc = (USB2_HC_DEV *) Context;
1469
1470 //
1471 // Stop the Host Controller
1472 //
1473 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
1474
1475 return;
1476 }
1477
1478
1479 /**
1480 Starting the Usb EHCI Driver.
1481
1482 @param This Protocol instance pointer.
1483 @param Controller Handle of device to test.
1484 @param RemainingDevicePath Not used.
1485
1486 @return EFI_SUCCESS supports this device.
1487 @return EFI_UNSUPPORTED do not support this device.
1488 @return EFI_DEVICE_ERROR cannot be started due to device Error.
1489 @return EFI_OUT_OF_RESOURCES cannot allocate resources.
1490
1491 **/
1492 EFI_STATUS
1493 EFIAPI
1494 EhcDriverBindingStart (
1495 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1496 IN EFI_HANDLE Controller,
1497 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1498 )
1499 {
1500 EFI_STATUS Status;
1501 USB2_HC_DEV *Ehc;
1502 EFI_PCI_IO_PROTOCOL *PciIo;
1503 EFI_PCI_IO_PROTOCOL *Instance;
1504 UINT64 Supports;
1505 UINT64 OriginalPciAttributes;
1506 BOOLEAN PciAttributesSaved;
1507 USB_CLASSC UsbClassCReg;
1508 EFI_HANDLE *HandleBuffer;
1509 UINTN NumberOfHandles;
1510 UINTN Index;
1511 UINTN UhciSegmentNumber;
1512 UINTN UhciBusNumber;
1513 UINTN UhciDeviceNumber;
1514 UINTN UhciFunctionNumber;
1515 UINTN EhciSegmentNumber;
1516 UINTN EhciBusNumber;
1517 UINTN EhciDeviceNumber;
1518 UINTN EhciFunctionNumber;
1519
1520 //
1521 // Open the PciIo Protocol, then enable the USB host controller
1522 //
1523 Status = gBS->OpenProtocol (
1524 Controller,
1525 &gEfiPciIoProtocolGuid,
1526 (VOID **) &PciIo,
1527 This->DriverBindingHandle,
1528 Controller,
1529 EFI_OPEN_PROTOCOL_BY_DRIVER
1530 );
1531
1532 if (EFI_ERROR (Status)) {
1533 return Status;
1534 }
1535
1536 PciAttributesSaved = FALSE;
1537 //
1538 // Save original PCI attributes
1539 //
1540 Status = PciIo->Attributes (
1541 PciIo,
1542 EfiPciIoAttributeOperationGet,
1543 0,
1544 &OriginalPciAttributes
1545 );
1546
1547 if (EFI_ERROR (Status)) {
1548 goto CLOSE_PCIIO;
1549 }
1550 PciAttributesSaved = TRUE;
1551
1552 Status = PciIo->Attributes (
1553 PciIo,
1554 EfiPciIoAttributeOperationSupported,
1555 0,
1556 &Supports
1557 );
1558 if (!EFI_ERROR (Status)) {
1559 Supports &= EFI_PCI_DEVICE_ENABLE;
1560 Status = PciIo->Attributes (
1561 PciIo,
1562 EfiPciIoAttributeOperationEnable,
1563 Supports,
1564 NULL
1565 );
1566 }
1567
1568 if (EFI_ERROR (Status)) {
1569 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to enable controller\n"));
1570 goto CLOSE_PCIIO;
1571 }
1572
1573 Status = PciIo->Pci.Read (
1574 PciIo,
1575 EfiPciIoWidthUint8,
1576 PCI_CLASSCODE_OFFSET,
1577 sizeof (USB_CLASSC) / sizeof (UINT8),
1578 &UsbClassCReg
1579 );
1580
1581 if (EFI_ERROR (Status)) {
1582 Status = EFI_UNSUPPORTED;
1583 goto CLOSE_PCIIO;
1584 }
1585
1586 if ((UsbClassCReg.PI == PCI_IF_UHCI) &&
1587 (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
1588 (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
1589 Status = PciIo->GetLocation (
1590 PciIo,
1591 &UhciSegmentNumber,
1592 &UhciBusNumber,
1593 &UhciDeviceNumber,
1594 &UhciFunctionNumber
1595 );
1596 if (EFI_ERROR (Status)) {
1597 goto CLOSE_PCIIO;
1598 }
1599
1600 Status = gBS->LocateHandleBuffer (
1601 ByProtocol,
1602 &gEfiPciIoProtocolGuid,
1603 NULL,
1604 &NumberOfHandles,
1605 &HandleBuffer
1606 );
1607 if (EFI_ERROR (Status)) {
1608 goto CLOSE_PCIIO;
1609 }
1610
1611 for (Index = 0; Index < NumberOfHandles; Index++) {
1612 //
1613 // Get the device path on this handle
1614 //
1615 Status = gBS->HandleProtocol (
1616 HandleBuffer[Index],
1617 &gEfiPciIoProtocolGuid,
1618 (VOID **)&Instance
1619 );
1620 ASSERT_EFI_ERROR (Status);
1621
1622 Status = Instance->Pci.Read (
1623 Instance,
1624 EfiPciIoWidthUint8,
1625 PCI_CLASSCODE_OFFSET,
1626 sizeof (USB_CLASSC) / sizeof (UINT8),
1627 &UsbClassCReg
1628 );
1629
1630 if (EFI_ERROR (Status)) {
1631 Status = EFI_UNSUPPORTED;
1632 goto CLOSE_PCIIO;
1633 }
1634
1635 if ((UsbClassCReg.PI == PCI_IF_EHCI) &&
1636 (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
1637 (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
1638 Status = Instance->GetLocation (
1639 Instance,
1640 &EhciSegmentNumber,
1641 &EhciBusNumber,
1642 &EhciDeviceNumber,
1643 &EhciFunctionNumber
1644 );
1645 if (EFI_ERROR (Status)) {
1646 goto CLOSE_PCIIO;
1647 }
1648 if (EhciBusNumber == UhciBusNumber) {
1649 gBS->CloseProtocol (
1650 Controller,
1651 &gEfiPciIoProtocolGuid,
1652 This->DriverBindingHandle,
1653 Controller
1654 );
1655 EhcDriverBindingStart(This, HandleBuffer[Index], NULL);
1656 }
1657 }
1658 }
1659 Status = EFI_NOT_FOUND;
1660 goto CLOSE_PCIIO;
1661 }
1662
1663 //
1664 // Create then install USB2_HC_PROTOCOL
1665 //
1666 Ehc = EhcCreateUsb2Hc (PciIo, OriginalPciAttributes);
1667
1668 if (Ehc == NULL) {
1669 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to create USB2_HC\n"));
1670
1671 Status = EFI_OUT_OF_RESOURCES;
1672 goto CLOSE_PCIIO;
1673 }
1674
1675 Status = gBS->InstallProtocolInterface (
1676 &Controller,
1677 &gEfiUsb2HcProtocolGuid,
1678 EFI_NATIVE_INTERFACE,
1679 &Ehc->Usb2Hc
1680 );
1681
1682 if (EFI_ERROR (Status)) {
1683 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
1684 goto FREE_POOL;
1685 }
1686
1687 //
1688 // Robustnesss improvement such as for UoL
1689 // Default is not required.
1690 //
1691 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
1692 EhcClearLegacySupport (Ehc);
1693 }
1694 EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
1695
1696 Status = EhcInitHC (Ehc);
1697
1698 if (EFI_ERROR (Status)) {
1699 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to init host controller\n"));
1700 goto UNINSTALL_USBHC;
1701 }
1702
1703 //
1704 // Start the asynchronous interrupt monitor
1705 //
1706 Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL);
1707
1708 if (EFI_ERROR (Status)) {
1709 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
1710
1711 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
1712 goto UNINSTALL_USBHC;
1713 }
1714
1715 //
1716 // Create event to stop the HC when exit boot service.
1717 //
1718 Status = gBS->CreateEventEx (
1719 EVT_NOTIFY_SIGNAL,
1720 TPL_NOTIFY,
1721 EhcExitBootService,
1722 Ehc,
1723 &gEfiEventExitBootServicesGuid,
1724 &Ehc->ExitBootServiceEvent
1725 );
1726 if (EFI_ERROR (Status)) {
1727 goto UNINSTALL_USBHC;
1728 }
1729
1730 //
1731 // Install the component name protocol, don't fail the start
1732 // because of something for display.
1733 //
1734 AddUnicodeString2 (
1735 "eng",
1736 gEhciComponentName.SupportedLanguages,
1737 &Ehc->ControllerNameTable,
1738 L"Enhanced Host Controller (USB 2.0)",
1739 TRUE
1740 );
1741 AddUnicodeString2 (
1742 "en",
1743 gEhciComponentName2.SupportedLanguages,
1744 &Ehc->ControllerNameTable,
1745 L"Enhanced Host Controller (USB 2.0)",
1746 FALSE
1747 );
1748
1749
1750 DEBUG ((EFI_D_INFO, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller));
1751 return EFI_SUCCESS;
1752
1753 UNINSTALL_USBHC:
1754 gBS->UninstallProtocolInterface (
1755 Controller,
1756 &gEfiUsb2HcProtocolGuid,
1757 &Ehc->Usb2Hc
1758 );
1759
1760 FREE_POOL:
1761 EhcFreeSched (Ehc);
1762 gBS->CloseEvent (Ehc->PollTimer);
1763 gBS->FreePool (Ehc);
1764
1765 CLOSE_PCIIO:
1766 if (PciAttributesSaved) {
1767 //
1768 // Restore original PCI attributes
1769 //
1770 PciIo->Attributes (
1771 PciIo,
1772 EfiPciIoAttributeOperationSet,
1773 OriginalPciAttributes,
1774 NULL
1775 );
1776 }
1777
1778 gBS->CloseProtocol (
1779 Controller,
1780 &gEfiPciIoProtocolGuid,
1781 This->DriverBindingHandle,
1782 Controller
1783 );
1784
1785 return Status;
1786 }
1787
1788
1789 /**
1790 Stop this driver on ControllerHandle. Support stoping any child handles
1791 created by this driver.
1792
1793 @param This Protocol instance pointer.
1794 @param Controller Handle of device to stop driver on.
1795 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
1796 @param ChildHandleBuffer List of handles for the children we need to stop.
1797
1798 @return EFI_SUCCESS Success.
1799 @return EFI_DEVICE_ERROR Fail.
1800
1801 **/
1802 EFI_STATUS
1803 EFIAPI
1804 EhcDriverBindingStop (
1805 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1806 IN EFI_HANDLE Controller,
1807 IN UINTN NumberOfChildren,
1808 IN EFI_HANDLE *ChildHandleBuffer
1809 )
1810 {
1811 EFI_STATUS Status;
1812 EFI_USB2_HC_PROTOCOL *Usb2Hc;
1813 EFI_PCI_IO_PROTOCOL *PciIo;
1814 USB2_HC_DEV *Ehc;
1815
1816 //
1817 // Test whether the Controller handler passed in is a valid
1818 // Usb controller handle that should be supported, if not,
1819 // return the error status directly
1820 //
1821 Status = gBS->OpenProtocol (
1822 Controller,
1823 &gEfiUsb2HcProtocolGuid,
1824 (VOID **) &Usb2Hc,
1825 This->DriverBindingHandle,
1826 Controller,
1827 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1828 );
1829
1830 if (EFI_ERROR (Status)) {
1831 return Status;
1832 }
1833
1834 Ehc = EHC_FROM_THIS (Usb2Hc);
1835 PciIo = Ehc->PciIo;
1836
1837 //
1838 // Stop AsyncRequest Polling timer then stop the EHCI driver
1839 // and uninstall the EHCI protocl.
1840 //
1841 gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL);
1842 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
1843
1844 Status = gBS->UninstallProtocolInterface (
1845 Controller,
1846 &gEfiUsb2HcProtocolGuid,
1847 Usb2Hc
1848 );
1849
1850 if (EFI_ERROR (Status)) {
1851 return Status;
1852 }
1853
1854 if (Ehc->PollTimer != NULL) {
1855 gBS->CloseEvent (Ehc->PollTimer);
1856 }
1857
1858 if (Ehc->ExitBootServiceEvent != NULL) {
1859 gBS->CloseEvent (Ehc->ExitBootServiceEvent);
1860 }
1861
1862 EhcFreeSched (Ehc);
1863
1864 if (Ehc->ControllerNameTable != NULL) {
1865 FreeUnicodeStringTable (Ehc->ControllerNameTable);
1866 }
1867
1868 //
1869 // Restore original PCI attributes
1870 //
1871 PciIo->Attributes (
1872 PciIo,
1873 EfiPciIoAttributeOperationSet,
1874 Ehc->OriginalPciAttributes,
1875 NULL
1876 );
1877
1878 gBS->CloseProtocol (
1879 Controller,
1880 &gEfiPciIoProtocolGuid,
1881 This->DriverBindingHandle,
1882 Controller
1883 );
1884
1885 FreePool (Ehc);
1886
1887 return EFI_SUCCESS;
1888 }
1889