]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
13ce7fdfb1f9f9f58b4e57f107e46d12a8103642
[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 = (UINT16) (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 = (UINT16) (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 = (UINT8) (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 EFI_STATUS
1275 EFIAPI
1276 EhcDriverEntryPoint (
1277 IN EFI_HANDLE ImageHandle,
1278 IN EFI_SYSTEM_TABLE *SystemTable
1279 )
1280 /*++
1281
1282 Routine Description:
1283
1284 Entry point for EFI drivers.
1285
1286 Arguments:
1287
1288 ImageHandle - EFI_HANDLE
1289 SystemTable - EFI_SYSTEM_TABLE
1290
1291 Returns:
1292
1293 EFI_SUCCESS Success
1294 EFI_DEVICE_ERROR Fail
1295
1296 --*/
1297 {
1298 return EfiLibInstallDriverBindingComponentName2 (
1299 ImageHandle,
1300 SystemTable,
1301 &gEhciDriverBinding,
1302 ImageHandle,
1303 &gEhciComponentName,
1304 &gEhciComponentName2
1305 );
1306 }
1307
1308
1309 /**
1310 Test to see if this driver supports ControllerHandle. Any
1311 ControllerHandle that has Usb2HcProtocol installed will
1312 be supported.
1313
1314 @param This Protocol instance pointer.
1315 @param Controlle Handle of device to test
1316 @param RemainingDevicePath Not used
1317
1318 @return EFI_SUCCESS : This driver supports this device.
1319 @return EFI_UNSUPPORTED : This driver does not support this device.
1320
1321 **/
1322 EFI_STATUS
1323 EFIAPI
1324 EhcDriverBindingSupported (
1325 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1326 IN EFI_HANDLE Controller,
1327 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1328 )
1329 {
1330 EFI_STATUS Status;
1331 EFI_PCI_IO_PROTOCOL *PciIo;
1332 USB_CLASSC UsbClassCReg;
1333
1334 //
1335 // Test whether there is PCI IO Protocol attached on the controller handle.
1336 //
1337 Status = gBS->OpenProtocol (
1338 Controller,
1339 &gEfiPciIoProtocolGuid,
1340 (VOID **) &PciIo,
1341 This->DriverBindingHandle,
1342 Controller,
1343 EFI_OPEN_PROTOCOL_BY_DRIVER
1344 );
1345
1346 if (EFI_ERROR (Status)) {
1347 return EFI_UNSUPPORTED;
1348 }
1349
1350 Status = PciIo->Pci.Read (
1351 PciIo,
1352 EfiPciIoWidthUint8,
1353 EHC_PCI_CLASSC,
1354 sizeof (USB_CLASSC) / sizeof (UINT8),
1355 &UsbClassCReg
1356 );
1357
1358 if (EFI_ERROR (Status)) {
1359 Status = EFI_UNSUPPORTED;
1360 goto ON_EXIT;
1361 }
1362
1363 //
1364 // Test whether the controller belongs to Ehci type
1365 //
1366 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
1367 (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
1368 (UsbClassCReg.PI != EHC_PCI_CLASSC_PI)) {
1369
1370 Status = EFI_UNSUPPORTED;
1371 }
1372
1373 ON_EXIT:
1374 gBS->CloseProtocol (
1375 Controller,
1376 &gEfiPciIoProtocolGuid,
1377 This->DriverBindingHandle,
1378 Controller
1379 );
1380
1381 return Status;
1382 }
1383
1384
1385 /**
1386 Create and initialize a USB2_HC_DEV
1387
1388 @param PciIo The PciIo on this device
1389
1390 @return The allocated and initialized USB2_HC_DEV structure
1391 @return if created, otherwise NULL.
1392
1393 **/
1394 STATIC
1395 USB2_HC_DEV *
1396 EhcCreateUsb2Hc (
1397 IN EFI_PCI_IO_PROTOCOL *PciIo
1398 )
1399 {
1400 USB2_HC_DEV *Ehc;
1401 EFI_STATUS Status;
1402
1403 Ehc = AllocateZeroPool (sizeof (USB2_HC_DEV));
1404
1405 if (Ehc == NULL) {
1406 return NULL;
1407 }
1408
1409 //
1410 // Init EFI_USB2_HC_PROTOCOL interface and private data structure
1411 //
1412 Ehc->Signature = USB2_HC_DEV_SIGNATURE;
1413
1414 Ehc->Usb2Hc.GetCapability = EhcGetCapability;
1415 Ehc->Usb2Hc.Reset = EhcReset;
1416 Ehc->Usb2Hc.GetState = EhcGetState;
1417 Ehc->Usb2Hc.SetState = EhcSetState;
1418 Ehc->Usb2Hc.ControlTransfer = EhcControlTransfer;
1419 Ehc->Usb2Hc.BulkTransfer = EhcBulkTransfer;
1420 Ehc->Usb2Hc.AsyncInterruptTransfer = EhcAsyncInterruptTransfer;
1421 Ehc->Usb2Hc.SyncInterruptTransfer = EhcSyncInterruptTransfer;
1422 Ehc->Usb2Hc.IsochronousTransfer = EhcIsochronousTransfer;
1423 Ehc->Usb2Hc.AsyncIsochronousTransfer = EhcAsyncIsochronousTransfer;
1424 Ehc->Usb2Hc.GetRootHubPortStatus = EhcGetRootHubPortStatus;
1425 Ehc->Usb2Hc.SetRootHubPortFeature = EhcSetRootHubPortFeature;
1426 Ehc->Usb2Hc.ClearRootHubPortFeature = EhcClearRootHubPortFeature;
1427 Ehc->Usb2Hc.MajorRevision = 0x1;
1428 Ehc->Usb2Hc.MinorRevision = 0x1;
1429
1430 Ehc->PciIo = PciIo;
1431
1432 InitializeListHead (&Ehc->AsyncIntTransfers);
1433
1434 Ehc->HcStructParams = EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET);
1435 Ehc->HcCapParams = EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET);
1436 Ehc->CapLen = EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET) & 0x0FF;
1437
1438 EHC_DEBUG (("EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen));
1439
1440 //
1441 // Create AsyncRequest Polling Timer
1442 //
1443 Status = gBS->CreateEvent (
1444 EVT_TIMER | EVT_NOTIFY_SIGNAL,
1445 TPL_CALLBACK,
1446 EhcMoniteAsyncRequests,
1447 Ehc,
1448 &Ehc->PollTimer
1449 );
1450
1451 if (EFI_ERROR (Status)) {
1452 gBS->FreePool (Ehc);
1453 return NULL;
1454 }
1455
1456 return Ehc;
1457 }
1458
1459
1460 /**
1461 Starting the Usb EHCI Driver
1462
1463 @param This Protocol instance pointer.
1464 @param Controller Handle of device to test
1465 @param RemainingDevicePath Not used
1466
1467 @return EFI_SUCCESS : supports this device.
1468 @return EFI_UNSUPPORTED : do not support this device.
1469 @return EFI_DEVICE_ERROR : cannot be started due to device Error
1470 @return EFI_OUT_OF_RESOURCES : cannot allocate resources
1471
1472 **/
1473 EFI_STATUS
1474 EFIAPI
1475 EhcDriverBindingStart (
1476 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1477 IN EFI_HANDLE Controller,
1478 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1479 )
1480 {
1481 EFI_STATUS Status;
1482 USB2_HC_DEV *Ehc;
1483 EFI_PCI_IO_PROTOCOL *PciIo;
1484
1485 //
1486 // Open the PciIo Protocol, then enable the USB host controller
1487 //
1488 Status = gBS->OpenProtocol (
1489 Controller,
1490 &gEfiPciIoProtocolGuid,
1491 (VOID **) &PciIo,
1492 This->DriverBindingHandle,
1493 Controller,
1494 EFI_OPEN_PROTOCOL_BY_DRIVER
1495 );
1496
1497 if (EFI_ERROR (Status)) {
1498 EHC_ERROR (("EhcDriverBindingStart: failed to open PCI_IO\n"));
1499 return EFI_DEVICE_ERROR;
1500 }
1501
1502 Status = PciIo->Attributes (
1503 PciIo,
1504 EfiPciIoAttributeOperationEnable,
1505 EFI_PCI_DEVICE_ENABLE,
1506 NULL
1507 );
1508
1509 if (EFI_ERROR (Status)) {
1510 EHC_ERROR (("EhcDriverBindingStart: failed to enable controller\n"));
1511 goto CLOSE_PCIIO;
1512 }
1513
1514 //
1515 // Create then install USB2_HC_PROTOCOL
1516 //
1517 Ehc = EhcCreateUsb2Hc (PciIo);
1518
1519 if (Ehc == NULL) {
1520 EHC_ERROR (("EhcDriverBindingStart: failed to create USB2_HC\n"));
1521
1522 Status = EFI_OUT_OF_RESOURCES;
1523 goto CLOSE_PCIIO;
1524 }
1525
1526 Status = gBS->InstallProtocolInterface (
1527 &Controller,
1528 &gEfiUsb2HcProtocolGuid,
1529 EFI_NATIVE_INTERFACE,
1530 &Ehc->Usb2Hc
1531 );
1532
1533 if (EFI_ERROR (Status)) {
1534 EHC_ERROR (("EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
1535 goto FREE_POOL;
1536 }
1537
1538 //
1539 // Robustnesss improvement such as for UoL
1540 //
1541 EhcClearLegacySupport (Ehc);
1542 EhcResetHC (Ehc, EHC_STALL_1_SECOND);
1543
1544 Status = EhcInitHC (Ehc);
1545
1546 if (EFI_ERROR (Status)) {
1547 EHC_ERROR (("EhcDriverBindingStart: failed to init host controller\n"));
1548 goto UNINSTALL_USBHC;
1549 }
1550
1551 //
1552 // Start the asynchronous interrupt monitor
1553 //
1554 Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_TIME);
1555
1556 if (EFI_ERROR (Status)) {
1557 EHC_ERROR (("EhcDriverBindingStart: failed to start async interrupt monitor\n"));
1558
1559 EhcHaltHC (Ehc, EHC_GENERIC_TIME);
1560 goto UNINSTALL_USBHC;
1561 }
1562
1563 //
1564 // Install the component name protocol, don't fail the start
1565 // because of something for display.
1566 //
1567 AddUnicodeString2 (
1568 "eng",
1569 gEhciComponentName.SupportedLanguages,
1570 &Ehc->ControllerNameTable,
1571 L"Enhanced Host Controller (USB 2.0)",
1572 TRUE
1573 );
1574 AddUnicodeString2 (
1575 "en",
1576 gEhciComponentName2.SupportedLanguages,
1577 &Ehc->ControllerNameTable,
1578 L"Enhanced Host Controller (USB 2.0)",
1579 FALSE
1580 );
1581
1582
1583 EHC_DEBUG (("EhcDriverBindingStart: EHCI started for controller @ %x\n", Controller));
1584 return EFI_SUCCESS;
1585
1586 UNINSTALL_USBHC:
1587 gBS->UninstallProtocolInterface (
1588 Controller,
1589 &gEfiUsb2HcProtocolGuid,
1590 &Ehc->Usb2Hc
1591 );
1592
1593 FREE_POOL:
1594 EhcFreeSched (Ehc);
1595 gBS->CloseEvent (Ehc->PollTimer);
1596 gBS->FreePool (Ehc);
1597
1598 CLOSE_PCIIO:
1599 gBS->CloseProtocol (
1600 Controller,
1601 &gEfiPciIoProtocolGuid,
1602 This->DriverBindingHandle,
1603 Controller
1604 );
1605
1606 return Status;
1607 }
1608
1609
1610 /**
1611 Stop this driver on ControllerHandle. Support stoping any child handles
1612 created by this driver.
1613
1614 @param This Protocol instance pointer.
1615 @param Controller Handle of device to stop driver on
1616 @param NumberOfChildren Number of Children in the ChildHandleBuffer
1617 @param ChildHandleBuffer List of handles for the children we need to stop.
1618
1619 @return EFI_SUCCESS Success
1620 @return EFI_DEVICE_ERROR Fail
1621
1622 **/
1623 EFI_STATUS
1624 EFIAPI
1625 EhcDriverBindingStop (
1626 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1627 IN EFI_HANDLE Controller,
1628 IN UINTN NumberOfChildren,
1629 IN EFI_HANDLE *ChildHandleBuffer
1630 )
1631 {
1632 EFI_STATUS Status;
1633 EFI_USB2_HC_PROTOCOL *Usb2Hc;
1634 EFI_PCI_IO_PROTOCOL *PciIo;
1635 USB2_HC_DEV *Ehc;
1636
1637 //
1638 // Test whether the Controller handler passed in is a valid
1639 // Usb controller handle that should be supported, if not,
1640 // return the error status directly
1641 //
1642 Status = gBS->OpenProtocol (
1643 Controller,
1644 &gEfiUsb2HcProtocolGuid,
1645 (VOID **) &Usb2Hc,
1646 This->DriverBindingHandle,
1647 Controller,
1648 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1649 );
1650
1651 if (EFI_ERROR (Status)) {
1652 return Status;
1653 }
1654
1655 Ehc = EHC_FROM_THIS (Usb2Hc);
1656 PciIo = Ehc->PciIo;
1657
1658 //
1659 // Stop AsyncRequest Polling timer then stop the EHCI driver
1660 // and uninstall the EHCI protocl.
1661 //
1662 gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_TIME);
1663 EhcHaltHC (Ehc, EHC_GENERIC_TIME);
1664
1665 Status = gBS->UninstallProtocolInterface (
1666 Controller,
1667 &gEfiUsb2HcProtocolGuid,
1668 Usb2Hc
1669 );
1670
1671 if (EFI_ERROR (Status)) {
1672 return Status;
1673 }
1674
1675 if (Ehc->PollTimer != NULL) {
1676 gBS->CloseEvent (Ehc->PollTimer);
1677 }
1678
1679 EhcFreeSched (Ehc);
1680
1681 if (Ehc->ControllerNameTable) {
1682 FreeUnicodeStringTable (Ehc->ControllerNameTable);
1683 }
1684
1685 //
1686 // Disable the USB Host Controller
1687 //
1688 PciIo->Attributes (
1689 PciIo,
1690 EfiPciIoAttributeOperationDisable,
1691 EFI_PCI_DEVICE_ENABLE,
1692 NULL
1693 );
1694
1695 gBS->CloseProtocol (
1696 Controller,
1697 &gEfiPciIoProtocolGuid,
1698 This->DriverBindingHandle,
1699 Controller
1700 );
1701
1702 gBS->FreePool (Ehc);
1703 return Status;
1704 }
1705
1706 EFI_DRIVER_BINDING_PROTOCOL
1707 gEhciDriverBinding = {
1708 EhcDriverBindingSupported,
1709 EhcDriverBindingStart,
1710 EhcDriverBindingStop,
1711 0x10,
1712 NULL,
1713 NULL
1714 };