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