]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.c
cb89e178f75b026b3f950427424a9538859bf11e
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / Ehci / Dxe / Ehci.c
1 /*++
2
3 Copyright (c) 2006, 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 #include "Ehci.h"
24
25
26 GLOBAL_REMOVE_IF_UNREFERENCED UINTN gEHCDebugLevel = EFI_D_ERROR;
27 GLOBAL_REMOVE_IF_UNREFERENCED UINTN gEHCErrorLevel = EFI_D_ERROR;
28
29
30 //
31 // Ehci Driver Global Variables
32 //
33 EFI_DRIVER_BINDING_PROTOCOL gEhciDriverBinding = {
34 EhciDriverBindingSupported,
35 EhciDriverBindingStart,
36 EhciDriverBindingStop,
37 0xa,
38 NULL,
39 NULL
40 };
41
42
43 EFI_STATUS
44 EFIAPI
45 EhciDriverBindingSupported (
46 IN EFI_DRIVER_BINDING_PROTOCOL *This,
47 IN EFI_HANDLE Controller,
48 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
49 )
50 /*++
51
52 Routine Description:
53
54 Test to see if this driver supports ControllerHandle. Any ControllerHandle
55 that has Usb2HcProtocol installed will be supported.
56
57 Arguments:
58
59 This - Protocol instance pointer.
60 Controlle - Handle of device to test
61 RemainingDevicePath - Not used
62
63 Returns:
64
65 EFI_SUCCESS This driver supports this device.
66 EFI_UNSUPPORTED This driver does not support this device.
67
68 --*/
69 {
70 EFI_STATUS Status;
71 EFI_PCI_IO_PROTOCOL *PciIo;
72 USB_CLASSC UsbClassCReg;
73
74
75 //
76 // Test whether there is PCI IO Protocol attached on the controller handle.
77 //
78 Status = gBS->OpenProtocol (
79 Controller,
80 &gEfiPciIoProtocolGuid,
81 (VOID **) &PciIo,
82 This->DriverBindingHandle,
83 Controller,
84 EFI_OPEN_PROTOCOL_BY_DRIVER
85 );
86 if (EFI_ERROR (Status)) {
87 goto exit;
88 }
89
90 Status = PciIo->Pci.Read (
91 PciIo,
92 EfiPciIoWidthUint8,
93 CLASSC,
94 sizeof (USB_CLASSC) / sizeof (UINT8),
95 &UsbClassCReg
96 );
97 if (EFI_ERROR (Status)) {
98 gBS->CloseProtocol (
99 Controller,
100 &gEfiPciIoProtocolGuid,
101 This->DriverBindingHandle,
102 Controller
103 );
104 Status = EFI_UNSUPPORTED;
105 goto exit;
106 }
107
108 //
109 // Test whether the controller belongs to Ehci type
110 //
111 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
112 (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
113 (UsbClassCReg.PI != PCI_CLASSC_PI_EHCI)
114 ) {
115
116 gBS->CloseProtocol (
117 Controller,
118 &gEfiPciIoProtocolGuid,
119 This->DriverBindingHandle,
120 Controller
121 );
122
123 Status = EFI_UNSUPPORTED;
124 goto exit;
125 }
126
127 gBS->CloseProtocol (
128 Controller,
129 &gEfiPciIoProtocolGuid,
130 This->DriverBindingHandle,
131 Controller
132 );
133
134 exit:
135 return Status;
136 }
137
138 EFI_STATUS
139 EFIAPI
140 EhciDriverBindingStart (
141 IN EFI_DRIVER_BINDING_PROTOCOL *This,
142 IN EFI_HANDLE Controller,
143 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
144 )
145 /*++
146
147 Routine Description:
148
149 Starting the Usb EHCI Driver
150
151 Arguments:
152
153 This - Protocol instance pointer.
154 Controller - Handle of device to test
155 RemainingDevicePath - Not used
156
157 Returns:
158
159 EFI_SUCCESS supports this device.
160 EFI_UNSUPPORTED do not support this device.
161 EFI_DEVICE_ERROR cannot be started due to device Error
162 EFI_OUT_OF_RESOURCES cannot allocate resources
163
164 --*/
165 {
166 EFI_STATUS Status;
167 USB2_HC_DEV *HcDev;
168 EFI_PCI_IO_PROTOCOL *PciIo;
169 UINT8 MaxSpeed;
170 UINT8 PortNumber;
171 UINT8 Is64BitCapable;
172 UINT64 Supports;
173
174 //
175 // Open the PciIo Protocol
176 //
177 Status = gBS->OpenProtocol (
178 Controller,
179 &gEfiPciIoProtocolGuid,
180 (VOID **) &PciIo,
181 This->DriverBindingHandle,
182 Controller,
183 EFI_OPEN_PROTOCOL_BY_DRIVER
184 );
185 if (EFI_ERROR (Status)) {
186 Status = EFI_OUT_OF_RESOURCES;
187 goto exit;
188 }
189
190 //
191 // Enable the USB Host Controller
192 //
193 Status = PciIo->Attributes (
194 PciIo,
195 EfiPciIoAttributeOperationSupported,
196 0,
197 &Supports
198 );
199 if (!EFI_ERROR (Status)) {
200 Supports &= EFI_PCI_DEVICE_ENABLE;
201 Status = PciIo->Attributes (
202 PciIo,
203 EfiPciIoAttributeOperationEnable,
204 Supports,
205 NULL
206 );
207 }
208 if (EFI_ERROR (Status)) {
209 Status = EFI_OUT_OF_RESOURCES;
210 goto close_pciio_protocol;
211 }
212
213 //
214 // Allocate memory for EHC private data structure
215 //
216 HcDev = AllocateZeroPool (sizeof (USB2_HC_DEV));
217 if (NULL == HcDev) {
218 Status = EFI_OUT_OF_RESOURCES;
219 goto close_pciio_protocol;
220 }
221
222 //
223 // Init EFI_USB2_HC_PROTOCOL interface and private data structure
224 //
225 HcDev->Usb2Hc.GetCapability = EhciGetCapability;
226 HcDev->Usb2Hc.Reset = EhciReset;
227 HcDev->Usb2Hc.GetState = EhciGetState;
228 HcDev->Usb2Hc.SetState = EhciSetState;
229 HcDev->Usb2Hc.ControlTransfer = EhciControlTransfer;
230 HcDev->Usb2Hc.BulkTransfer = EhciBulkTransfer;
231 HcDev->Usb2Hc.AsyncInterruptTransfer = EhciAsyncInterruptTransfer;
232 HcDev->Usb2Hc.SyncInterruptTransfer = EhciSyncInterruptTransfer;
233 HcDev->Usb2Hc.IsochronousTransfer = EhciIsochronousTransfer;
234 HcDev->Usb2Hc.AsyncIsochronousTransfer = EhciAsyncIsochronousTransfer;
235 HcDev->Usb2Hc.GetRootHubPortStatus = EhciGetRootHubPortStatus;
236 HcDev->Usb2Hc.SetRootHubPortFeature = EhciSetRootHubPortFeature;
237 HcDev->Usb2Hc.ClearRootHubPortFeature = EhciClearRootHubPortFeature;
238 HcDev->Usb2Hc.MajorRevision = 0x1;
239 HcDev->Usb2Hc.MinorRevision = 0x1;
240
241 HcDev->AsyncRequestList = NULL;
242 HcDev->ControllerNameTable = NULL;
243 HcDev->Signature = USB2_HC_DEV_SIGNATURE;
244 HcDev->PciIo = PciIo;
245
246 //
247 // Install USB2_HC_PROTOCOL
248 //
249 Status = gBS->InstallProtocolInterface (
250 &Controller,
251 &gEfiUsb2HcProtocolGuid,
252 EFI_NATIVE_INTERFACE,
253 &HcDev->Usb2Hc
254 );
255 if (EFI_ERROR (Status)) {
256 Status = EFI_OUT_OF_RESOURCES;
257 goto free_pool;
258 }
259
260 //
261 // Get Capability Register Length
262 //
263 Status = GetCapabilityLen (HcDev);
264 if (EFI_ERROR (Status)) {
265 Status = EFI_DEVICE_ERROR;
266 goto uninstall_usb2hc_protocol;
267 }
268
269 ClearLegacySupport (HcDev);
270 HostReset (HcDev);
271
272 DEBUG_CODE (
273 DumpEHCIPortsStatus (HcDev);
274 );
275
276 //
277 // Create and Init Perodic Frame List
278 //
279 Status = EhciGetCapability (
280 &HcDev->Usb2Hc,
281 &MaxSpeed,
282 &PortNumber,
283 &Is64BitCapable
284 );
285 if (EFI_ERROR (Status)) {
286 Status = EFI_OUT_OF_RESOURCES;
287 goto uninstall_usb2hc_protocol;
288 }
289 HcDev->Is64BitCapable = Is64BitCapable;
290
291 //
292 // Create and Init Perodic Frame List
293 //
294 Status = InitialPeriodicFrameList (
295 HcDev,
296 EHCI_MAX_FRAME_LIST_LENGTH
297 );
298 if (EFI_ERROR (Status)) {
299 Status = EFI_OUT_OF_RESOURCES;
300 goto uninstall_usb2hc_protocol;
301 }
302
303 //
304 // Init memory pool management
305 //
306 Status = InitialMemoryManagement (HcDev);
307 if (EFI_ERROR (Status)) {
308 Status = EFI_OUT_OF_RESOURCES;
309 goto deinit_perodic_frame_list;
310 }
311
312 Status = CreateNULLQH (HcDev);
313 if (EFI_ERROR (Status)) {
314 Status = EFI_OUT_OF_RESOURCES;
315 goto deinit_perodic_frame_list;
316 }
317 //
318 // Create AsyncRequest Polling Timer
319 //
320 Status = CreatePollingTimer (HcDev, (EFI_EVENT_NOTIFY) AsyncRequestMoniter);
321 if (EFI_ERROR (Status)) {
322 Status = EFI_OUT_OF_RESOURCES;
323 goto deinit_null_qh;
324 }
325
326 //
327 // Default Maxximum Interrupt Interval is 8,
328 // it means that 8 micro frame = 1ms
329 //
330
331 //
332 // Start the Host Controller
333 //
334 if (IsEhcHalted (HcDev)) {
335 Status = StartScheduleExecution (HcDev);
336 if (EFI_ERROR (Status)) {
337 Status = EFI_DEVICE_ERROR;
338 goto deinit_timer;
339 }
340 }
341
342 //
343 // Set all ports routing to EHC
344 //
345 Status = SetPortRoutingEhc (HcDev);
346 if (EFI_ERROR (Status)) {
347 Status = EFI_DEVICE_ERROR;
348 goto deinit_timer;
349 }
350
351 //
352 // Component name protocol
353 //
354 Status = AddUnicodeString (
355 "eng",
356 gEhciComponentName.SupportedLanguages,
357 &HcDev->ControllerNameTable,
358 L"Usb Enhanced Host Controller"
359 );
360 if (EFI_ERROR (Status)) {
361 Status = EFI_OUT_OF_RESOURCES;
362 goto deinit_timer;
363 }
364
365 goto exit;
366
367 //
368 // Error handle process
369 //
370 deinit_timer:
371 DestoryPollingTimer (HcDev);
372 deinit_null_qh:
373 DestroyNULLQH(HcDev);
374 DeinitialMemoryManagement (HcDev);
375 deinit_perodic_frame_list:
376 DeinitialPeriodicFrameList (HcDev);
377 uninstall_usb2hc_protocol:
378 gBS->UninstallProtocolInterface (
379 Controller,
380 &gEfiUsb2HcProtocolGuid,
381 &HcDev->Usb2Hc
382 );
383 free_pool:
384 gBS->FreePool (HcDev);
385 close_pciio_protocol:
386 gBS->CloseProtocol (
387 Controller,
388 &gEfiPciIoProtocolGuid,
389 This->DriverBindingHandle,
390 Controller
391 );
392
393 exit:
394 return Status;
395 }
396
397 EFI_STATUS
398 EFIAPI
399 EhciDriverBindingStop (
400 IN EFI_DRIVER_BINDING_PROTOCOL *This,
401 IN EFI_HANDLE Controller,
402 IN UINTN NumberOfChildren,
403 IN EFI_HANDLE *ChildHandleBuffer
404 )
405 /*++
406
407 Routine Description:
408
409 Stop this driver on ControllerHandle. Support stoping any child handles
410 created by this driver.
411
412 Arguments:
413
414 This - Protocol instance pointer.
415 Controller - Handle of device to stop driver on
416 NumberOfChildren - Number of Children in the ChildHandleBuffer
417 ChildHandleBuffer - List of handles for the children we need to stop.
418
419 Returns:
420
421 EFI_SUCCESS Success
422 EFI_DEVICE_ERROR Fail
423 --*/
424 {
425 EFI_STATUS Status;
426 EFI_USB2_HC_PROTOCOL *Usb2Hc;
427 USB2_HC_DEV *HcDev;
428 UINT64 Supports;
429
430 //
431 // Test whether the Controller handler passed in is a valid
432 // Usb controller handle that should be supported, if not,
433 // return the error status directly
434 //
435 Status = gBS->OpenProtocol (
436 Controller,
437 &gEfiUsb2HcProtocolGuid,
438 (VOID **) &Usb2Hc,
439 This->DriverBindingHandle,
440 Controller,
441 EFI_OPEN_PROTOCOL_GET_PROTOCOL
442 );
443 if (EFI_ERROR (Status)) {
444 Status = EFI_DEVICE_ERROR;
445 goto exit;
446 }
447
448 HcDev = USB2_HC_DEV_FROM_THIS (Usb2Hc);
449
450 //
451 // free all the controller related memory and uninstall UHCI Protocol.
452 //
453 Status = gBS->UninstallProtocolInterface (
454 Controller,
455 &gEfiUsb2HcProtocolGuid,
456 Usb2Hc
457 );
458 if (EFI_ERROR (Status)) {
459 Status = EFI_DEVICE_ERROR;
460 goto exit;
461 }
462
463 //
464 // Set Host Controller state as halt
465 //
466 Status = Usb2Hc->SetState (
467 Usb2Hc,
468 EfiUsbHcStateHalt
469 );
470 if (EFI_ERROR (Status)) {
471 Status = EFI_DEVICE_ERROR;
472 goto exit;
473 }
474
475 //
476 // Stop AsyncRequest Polling Timer
477 //
478 Status = StopPollingTimer (HcDev);
479 if (EFI_ERROR (Status)) {
480 Status = EFI_DEVICE_ERROR;
481 goto exit;
482 }
483
484 //
485 // Destroy Asynchronous Request Event
486 //
487 DestoryPollingTimer (HcDev);
488
489 //
490 // Destroy Perodic Frame List
491 //
492 DeinitialPeriodicFrameList (HcDev);
493
494 //
495 // Destroy NULLQH
496 //
497 DestroyNULLQH (HcDev);
498
499 //
500 // Deinit Ehci pool memory management
501 //
502 DeinitialMemoryManagement (HcDev);
503
504 //
505 // Denint Unicode String Table
506 //
507 FreeUnicodeStringTable (HcDev->ControllerNameTable);
508
509 //
510 // Disable the USB Host Controller
511 //
512 Status = HcDev->PciIo->Attributes (
513 HcDev->PciIo,
514 EfiPciIoAttributeOperationSupported,
515 0,
516 &Supports
517 );
518 if (!EFI_ERROR (Status)) {
519 Supports &= EFI_PCI_DEVICE_ENABLE;
520 Status = HcDev->PciIo->Attributes (
521 HcDev->PciIo,
522 EfiPciIoAttributeOperationDisable,
523 Supports,
524 NULL
525 );
526 }
527 if (EFI_ERROR (Status)) {
528 Status = EFI_DEVICE_ERROR;
529 goto exit;
530 }
531
532 gBS->FreePool (HcDev);
533
534 gBS->CloseProtocol (
535 Controller,
536 &gEfiPciIoProtocolGuid,
537 This->DriverBindingHandle,
538 Controller
539 );
540
541 exit:
542 return Status;
543 }
544
545 EFI_STATUS
546 EFIAPI
547 EhciGetCapability (
548 IN EFI_USB2_HC_PROTOCOL *This,
549 OUT UINT8 *MaxSpeed,
550 OUT UINT8 *PortNumber,
551 OUT UINT8 *Is64BitCapable
552 )
553 /*++
554
555 Routine Description:
556
557 Retrieves the capablility of root hub ports.
558
559 Arguments:
560
561 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
562 MaxSpeed - A pointer to the number of the host controller.
563 PortNumber - A pointer to the number of the root hub ports.
564 Is64BitCapable - A pointer to the flag for whether controller supports
565 64-bit memory addressing.
566
567 Returns:
568
569 EFI_SUCCESS host controller capability were retrieved successfully.
570 EFI_INVALID_PARAMETER MaxSpeed or PortNumber or Is64BitCapable is NULL.
571 EFI_DEVICE_ERROR An error was encountered while attempting to retrieve the capabilities.
572
573 --*/
574 {
575 EFI_STATUS Status;
576 USB2_HC_DEV *HcDev;
577 UINT32 HcStructParamsAddr;
578 UINT32 HcStructParamsReg;
579 UINT32 HcCapParamsAddr;
580 UINT32 HcCapParamsReg;
581
582 if (MaxSpeed == NULL || PortNumber == NULL || Is64BitCapable == NULL) {
583 Status = EFI_INVALID_PARAMETER;
584 goto exit;
585 }
586
587 HcStructParamsAddr = HCSPARAMS;
588 HcCapParamsAddr = HCCPARAMS;
589 HcDev = USB2_HC_DEV_FROM_THIS (This);
590
591 Status = ReadEhcCapabiltiyReg (
592 HcDev,
593 HcStructParamsAddr,
594 &HcStructParamsReg
595 );
596 if (EFI_ERROR (Status)) {
597 Status = EFI_DEVICE_ERROR;
598 goto exit;
599 }
600
601 Status = ReadEhcCapabiltiyReg (
602 HcDev,
603 HcCapParamsAddr,
604 &HcCapParamsReg
605 );
606 if (EFI_ERROR (Status)) {
607 Status = EFI_DEVICE_ERROR;
608 goto exit;
609 }
610
611 *MaxSpeed = EFI_USB_SPEED_HIGH;
612 *PortNumber = (UINT8) (HcStructParamsReg & HCSP_NPORTS);
613 *Is64BitCapable = (UINT8) (HcCapParamsReg & HCCP_64BIT);
614
615 exit:
616 return Status;
617 }
618
619 EFI_STATUS
620 EFIAPI
621 EhciReset (
622 IN EFI_USB2_HC_PROTOCOL *This,
623 IN UINT16 Attributes
624 )
625 /*++
626
627 Routine Description:
628
629 Provides software reset for the USB host controller.
630
631 Arguments:
632
633 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
634 Attributes - A bit mask of the reset operation to perform.
635 See below for a list of the supported bit mask values.
636
637 #define EFI_USB_HC_RESET_GLOBAL 0x0001
638 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002
639 #define EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG 0x0004
640 #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008
641
642 EFI_USB_HC_RESET_GLOBAL
643 If this bit is set, a global reset signal will be sent to the USB bus.
644 This resets all of the USB bus logic, including the USB host
645 controller hardware and all the devices attached on the USB bus.
646 EFI_USB_HC_RESET_HOST_CONTROLLER
647 If this bit is set, the USB host controller hardware will be reset.
648 No reset signal will be sent to the USB bus.
649 EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
650 If this bit is set, a global reset signal will be sent to the USB bus.
651 This resets all of the USB bus logic, including the USB host
652 controller hardware and all the devices attached on the USB bus.
653 If this is an EHCI controller and the debug port has configured, then
654 this is will still reset the host controller.
655 EFI_USB_HC_RESET_HOST_WITH_DEBUG
656 If this bit is set, the USB host controller hardware will be reset.
657 If this is an EHCI controller and the debug port has been configured,
658 then this will still reset the host controller.
659
660 Returns:
661
662 EFI_SUCCESS
663 The reset operation succeeded.
664 EFI_INVALID_PARAMETER
665 Attributes is not valid.
666 EFI_UNSUPPOURTED
667 The type of reset specified by Attributes is not currently supported by
668 the host controller hardware.
669 EFI_ACCESS_DENIED
670 Reset operation is rejected due to the debug port being configured and
671 active; only EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG or
672 EFI_USB_HC_RESET_HOST_WITH_DEBUG reset Atrributes can be used to
673 perform reset operation for this host controller.
674 EFI_DEVICE_ERROR
675 An error was encountered while attempting to perform
676 the reset operation.
677
678 --*/
679 {
680 EFI_STATUS Status;
681 USB2_HC_DEV *HcDev;
682 UINTN FrameIndex;
683 FRAME_LIST_ENTRY *FrameEntryPtr;
684
685 HcDev = USB2_HC_DEV_FROM_THIS (This);
686
687 switch (Attributes) {
688
689 case EFI_USB_HC_RESET_GLOBAL:
690
691 //
692 // Same behavior as Host Controller Reset
693 //
694
695 case EFI_USB_HC_RESET_HOST_CONTROLLER:
696
697 //
698 // Host Controller must be Halt when Reset it
699 //
700 if (IsEhcHalted (HcDev)) {
701 Status = ResetEhc (HcDev);
702 if (EFI_ERROR (Status)) {
703 Status = EFI_DEVICE_ERROR;
704 goto exit;
705 }
706 //
707 // Set to zero by Host Controller when reset process completes
708 //
709 Status = WaitForEhcReset (HcDev, EHCI_GENERIC_TIMEOUT);
710 if (EFI_ERROR (Status)) {
711 Status = EFI_TIMEOUT;
712 goto exit;
713 }
714 } else {
715 Status = EFI_DEVICE_ERROR;
716 goto exit;
717 }
718
719 //
720 // only asynchronous interrupt transfers are always alive on the bus, need to cleanup
721 //
722 CleanUpAllAsyncRequestTransfer (HcDev);
723 Status = ClearEhcAllStatus (HcDev);
724 if (EFI_ERROR (Status)) {
725 Status = EFI_DEVICE_ERROR;
726 goto exit;
727 }
728
729 //
730 // Set appropriate 4G Segment Selector
731 //
732 Status = SetCtrlDataStructSeg (HcDev);
733 if (EFI_ERROR (Status)) {
734 Status = EFI_DEVICE_ERROR;
735 goto exit;
736 }
737
738 //
739 // Init Perodic List Base Addr and Frame List
740 //
741 Status = SetFrameListBaseAddr (
742 HcDev,
743 (UINT32)GET_0B_TO_31B (HcDev->PeriodicFrameListBuffer)
744 );
745 if (EFI_ERROR (Status)) {
746 Status = EFI_DEVICE_ERROR;
747 goto exit;
748 }
749 FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;
750 for (FrameIndex = 0; FrameIndex < HcDev->PeriodicFrameListLength; FrameIndex++) {
751 FrameEntryPtr->LinkTerminate = TRUE;
752 FrameEntryPtr++;
753 }
754
755 //
756 // Start the Host Controller
757 //
758 if (IsEhcHalted (HcDev)) {
759 Status = StartScheduleExecution (HcDev);
760 if (EFI_ERROR (Status)) {
761 Status = EFI_DEVICE_ERROR;
762 goto exit;
763 }
764 }
765
766 //
767 // Set all ports routing to EHC
768 //
769 Status = SetPortRoutingEhc (HcDev);
770 if (EFI_ERROR (Status)) {
771 Status = EFI_DEVICE_ERROR;
772 goto exit;
773 }
774 break;
775
776 case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:
777
778 Status = EFI_UNSUPPORTED;
779 break;
780
781 case EFI_USB_HC_RESET_HOST_WITH_DEBUG:
782
783 Status = EFI_UNSUPPORTED;
784 break;
785
786 default:
787 Status = EFI_INVALID_PARAMETER;
788 }
789
790 exit:
791 return Status;
792 }
793
794 EFI_STATUS
795 EFIAPI
796 EhciGetState (
797 IN EFI_USB2_HC_PROTOCOL *This,
798 OUT EFI_USB_HC_STATE *State
799 )
800 /*++
801
802 Routine Description:
803
804 Retrieves current state of the USB host controller.
805
806 Arguments:
807
808 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
809 State A pointer to the EFI_USB_HC_STATE data structure that
810 indicates current state of the USB host controller.
811 Type EFI_USB_HC_STATE is defined below.
812
813 typedef enum {
814 EfiUsbHcStateHalt,
815 EfiUsbHcStateOperational,
816 EfiUsbHcStateSuspend,
817 EfiUsbHcStateMaximum
818 } EFI_USB_HC_STATE;
819
820 Returns:
821
822 EFI_SUCCESS
823 The state information of the host controller was returned in State.
824 EFI_INVALID_PARAMETER
825 State is NULL.
826 EFI_DEVICE_ERROR
827 An error was encountered while attempting to retrieve the
828 host controller's current state.
829 --*/
830 {
831 EFI_STATUS Status;
832 USB2_HC_DEV *HcDev;
833 UINT32 UsbStatusAddr;
834 UINT32 UsbStatusReg;
835
836 if (State == NULL) {
837 Status = EFI_INVALID_PARAMETER;
838 goto exit;
839 }
840
841 UsbStatusAddr = USBSTS;
842 HcDev = USB2_HC_DEV_FROM_THIS (This);
843
844 Status = ReadEhcOperationalReg (
845 HcDev,
846 UsbStatusAddr,
847 &UsbStatusReg
848 );
849 if (EFI_ERROR (Status)) {
850 Status = EFI_DEVICE_ERROR;
851 goto exit;
852 }
853
854 if (UsbStatusReg & USBSTS_HCH) {
855 *State = EfiUsbHcStateHalt;
856 } else {
857 *State = EfiUsbHcStateOperational;
858 }
859
860 exit:
861 return Status;
862 }
863
864 EFI_STATUS
865 EFIAPI
866 EhciSetState (
867 IN EFI_USB2_HC_PROTOCOL *This,
868 IN EFI_USB_HC_STATE State
869 )
870 /*++
871
872 Routine Description:
873
874 Sets the USB host controller to a specific state.
875
876 Arguments:
877
878 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
879 State - Indicates the state of the host controller that will be set.
880
881 Returns:
882
883 EFI_SUCCESS
884 The USB host controller was successfully placed in the state
885 specified by State.
886 EFI_INVALID_PARAMETER
887 State is invalid.
888 EFI_DEVICE_ERROR
889 Failed to set the state specified by State due to device error.
890
891 --*/
892 {
893 EFI_STATUS Status;
894 USB2_HC_DEV *HcDev;
895 UINT32 UsbCommandAddr;
896 UINT32 UsbCommandReg;
897 EFI_USB_HC_STATE CurrentState;
898
899 UsbCommandAddr = USBCMD;
900 HcDev = USB2_HC_DEV_FROM_THIS (This);
901
902 Status = EhciGetState (This, &CurrentState);
903 if (EFI_ERROR (Status)) {
904 Status = EFI_DEVICE_ERROR;
905 goto exit;
906 }
907
908 switch (State) {
909
910 case EfiUsbHcStateHalt:
911
912 if (EfiUsbHcStateHalt == CurrentState) {
913 Status = EFI_SUCCESS;
914 goto exit;
915 } else if (EfiUsbHcStateOperational == CurrentState) {
916 Status = ReadEhcOperationalReg (
917 HcDev,
918 UsbCommandAddr,
919 &UsbCommandReg
920 );
921 if (EFI_ERROR (Status)) {
922 Status = EFI_DEVICE_ERROR;
923 goto exit;
924 }
925
926 UsbCommandReg &= ~USBCMD_RS;
927 Status = WriteEhcOperationalReg (
928 HcDev,
929 UsbCommandAddr,
930 UsbCommandReg
931 );
932 if (EFI_ERROR (Status)) {
933 Status = EFI_DEVICE_ERROR;
934 goto exit;
935 }
936 //
937 // Ensure the HC is in halt status after send the stop command
938 //
939 Status = WaitForEhcHalt (HcDev, EHCI_GENERIC_TIMEOUT);
940 if (EFI_ERROR (Status)) {
941 Status = EFI_TIMEOUT;
942 goto exit;
943 }
944 }
945 break;
946
947 case EfiUsbHcStateOperational:
948
949 if (IsEhcSysError (HcDev)) {
950 Status = EFI_DEVICE_ERROR;
951 goto exit;
952 }
953 if (EfiUsbHcStateOperational == CurrentState) {
954 Status = EFI_SUCCESS;
955 goto exit;
956 } else if (EfiUsbHcStateHalt == CurrentState) {
957 //
958 // Set Host Controller Run
959 //
960 Status = ReadEhcOperationalReg (
961 HcDev,
962 UsbCommandAddr,
963 &UsbCommandReg
964 );
965 if (EFI_ERROR (Status)) {
966 return EFI_DEVICE_ERROR;
967 }
968
969 UsbCommandReg |= USBCMD_RS;
970 Status = WriteEhcOperationalReg (
971 HcDev,
972 UsbCommandAddr,
973 UsbCommandReg
974 );
975 if (EFI_ERROR (Status)) {
976 Status = EFI_DEVICE_ERROR;
977 goto exit;
978 }
979 }
980 break;
981
982 case EfiUsbHcStateSuspend:
983
984 Status = EFI_UNSUPPORTED;
985 break;
986
987 default:
988
989 Status = EFI_INVALID_PARAMETER;
990 }
991
992 exit:
993 return Status;
994 }
995
996 EFI_STATUS
997 EFIAPI
998 EhciGetRootHubPortStatus (
999 IN EFI_USB2_HC_PROTOCOL *This,
1000 IN UINT8 PortNumber,
1001 OUT EFI_USB_PORT_STATUS *PortStatus
1002 )
1003 /*++
1004
1005 Routine Description:
1006
1007 Retrieves the current status of a USB root hub port.
1008
1009 Arguments:
1010
1011 This - A pointer to the EFI_USB2_HC_PROTOCOL.
1012 PortNumber - Specifies the root hub port from which the status
1013 is to be retrieved. This value is zero-based. For example,
1014 if a root hub has two ports, then the first port is numbered 0,
1015 and the second port is numbered 1.
1016 PortStatus - A pointer to the current port status bits and
1017 port status change bits.
1018
1019 Returns:
1020
1021 EFI_SUCCESS The status of the USB root hub port specified
1022 by PortNumber was returned in PortStatus.
1023 EFI_INVALID_PARAMETER PortNumber is invalid.
1024 EFI_DEVICE_ERROR Can't read register
1025
1026 --*/
1027 {
1028 EFI_STATUS Status;
1029 USB2_HC_DEV *HcDev;
1030 UINT32 PortStatusControlAddr;
1031 UINT32 PortStatusControlReg;
1032 UINT8 MaxSpeed;
1033 UINT8 TotalPortNumber;
1034 UINT8 Is64BitCapable;
1035
1036 if (PortStatus == NULL) {
1037 Status = EFI_INVALID_PARAMETER;
1038 goto exit;
1039 }
1040
1041 EhciGetCapability (
1042 This,
1043 &MaxSpeed,
1044 &TotalPortNumber,
1045 &Is64BitCapable
1046 );
1047
1048 if (PortNumber >= TotalPortNumber) {
1049 Status = EFI_INVALID_PARAMETER;
1050 goto exit;
1051 }
1052
1053 HcDev = USB2_HC_DEV_FROM_THIS (This);
1054 PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber));
1055
1056 //
1057 // Clear port status
1058 //
1059 PortStatus->PortStatus = 0;
1060 PortStatus->PortChangeStatus = 0;
1061
1062 Status = ReadEhcOperationalReg (
1063 HcDev,
1064 PortStatusControlAddr,
1065 &PortStatusControlReg
1066 );
1067 if (EFI_ERROR (Status)) {
1068 Status = EFI_DEVICE_ERROR;
1069 goto exit;
1070 }
1071
1072 //
1073 // Fill Port Status bits
1074 //
1075
1076 //
1077 // Current Connect Status
1078 //
1079 if (PORTSC_CCS & PortStatusControlReg) {
1080 PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
1081 }
1082 //
1083 // Port Enabled/Disabled
1084 //
1085 if (PORTSC_PED & PortStatusControlReg) {
1086 PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
1087 }
1088 //
1089 // Port Suspend
1090 //
1091 if (PORTSC_SUSP & PortStatusControlReg) {
1092 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
1093 }
1094 //
1095 // Over-current Active
1096 //
1097 if (PORTSC_OCA & PortStatusControlReg) {
1098 PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
1099 }
1100 //
1101 // Port Reset
1102 //
1103 if (PORTSC_PR & PortStatusControlReg) {
1104 PortStatus->PortStatus |= USB_PORT_STAT_RESET;
1105 }
1106 //
1107 // Port Power
1108 //
1109 if (PORTSC_PP & PortStatusControlReg) {
1110 PortStatus->PortStatus |= USB_PORT_STAT_POWER;
1111 }
1112 //
1113 // Port Owner
1114 //
1115 if (PORTSC_PO & PortStatusControlReg) {
1116 PortStatus->PortStatus |= USB_PORT_STAT_OWNER;
1117 }
1118 //
1119 // Identify device speed
1120 //
1121 if (PORTSC_LS_KSTATE & PortStatusControlReg) {
1122 //
1123 // Low Speed Device Attached
1124 //
1125 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
1126 } else {
1127 //
1128 // Not Low Speed Device Attached
1129 //
1130 if ((PORTSC_CCS & PortStatusControlReg) && (PORTSC_CSC & PortStatusControlReg)) {
1131 HcDev->DeviceSpeed[PortNumber] = (UINT16) (IsHighSpeedDevice (This, PortNumber) ? USB_PORT_STAT_HIGH_SPEED : 0);
1132 }
1133 PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | HcDev->DeviceSpeed[PortNumber]);
1134 }
1135 //
1136 // Fill Port Status Change bits
1137 //
1138 //
1139 // Connect Status Change
1140 //
1141 if (PORTSC_CSC & PortStatusControlReg) {
1142 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
1143 }
1144 //
1145 // Port Enabled/Disabled Change
1146 //
1147 if (PORTSC_PEDC & PortStatusControlReg) {
1148 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
1149 }
1150 //
1151 // Port Over Current Change
1152 //
1153 if (PORTSC_OCC & PortStatusControlReg) {
1154 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
1155 }
1156
1157 exit:
1158 return Status;
1159 }
1160
1161 EFI_STATUS
1162 EFIAPI
1163 EhciSetRootHubPortFeature (
1164 IN EFI_USB2_HC_PROTOCOL *This,
1165 IN UINT8 PortNumber,
1166 IN EFI_USB_PORT_FEATURE PortFeature
1167 )
1168 /*++
1169
1170 Routine Description:
1171
1172 Sets a feature for the specified root hub port.
1173
1174 Arguments:
1175
1176 This - A pointer to the EFI_USB2_HC_PROTOCOL.
1177 PortNumber - Specifies the root hub port whose feature
1178 is requested to be set.
1179 PortFeature - Indicates the feature selector associated
1180 with the feature set request.
1181
1182 Returns:
1183
1184 EFI_SUCCESS
1185 The feature specified by PortFeature was set for the
1186 USB root hub port specified by PortNumber.
1187 EFI_INVALID_PARAMETER
1188 PortNumber is invalid or PortFeature is invalid.
1189 EFI_DEVICE_ERROR
1190 Can't read register
1191
1192 --*/
1193 {
1194 EFI_STATUS Status;
1195 USB2_HC_DEV *HcDev;
1196 UINT32 PortStatusControlAddr;
1197 UINT32 PortStatusControlReg;
1198 UINT8 MaxSpeed;
1199 UINT8 TotalPortNumber;
1200 UINT8 Is64BitCapable;
1201
1202 EhciGetCapability (
1203 This,
1204 &MaxSpeed,
1205 &TotalPortNumber,
1206 &Is64BitCapable
1207 );
1208
1209 if (PortNumber >= TotalPortNumber) {
1210 Status = EFI_INVALID_PARAMETER;
1211 goto exit;
1212 }
1213
1214 HcDev = USB2_HC_DEV_FROM_THIS (This);
1215 PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber));
1216
1217 Status = ReadEhcOperationalReg (
1218 HcDev,
1219 PortStatusControlAddr,
1220 &PortStatusControlReg
1221 );
1222 if (EFI_ERROR (Status)) {
1223 Status = EFI_DEVICE_ERROR;
1224 goto exit;
1225 }
1226
1227 switch (PortFeature) {
1228
1229 case EfiUsbPortEnable:
1230
1231 //
1232 // Sofeware can't set this bit, Port can only be enable by the Host Controller
1233 // as a part of the reset and enable
1234 //
1235 PortStatusControlReg &= 0xffffffd5;
1236 PortStatusControlReg |= PORTSC_PED;
1237 break;
1238
1239 case EfiUsbPortSuspend:
1240
1241 PortStatusControlReg &= 0xffffffd5;
1242 PortStatusControlReg |= PORTSC_SUSP;
1243 break;
1244
1245 case EfiUsbPortReset:
1246
1247 //
1248 // Make sure Host Controller not halt before reset it
1249 //
1250 if (IsEhcHalted (HcDev)) {
1251 Status = StartScheduleExecution (HcDev);
1252 if (EFI_ERROR (Status)) {
1253 Status = EFI_DEVICE_ERROR;
1254 goto exit;
1255 }
1256 Status = WaitForEhcNotHalt (HcDev, EHCI_GENERIC_TIMEOUT);
1257 if (EFI_ERROR (Status)) {
1258 DEBUG ((gEHCDebugLevel, "EHCI: WaitForEhcNotHalt TimeOut\n"));
1259 Status = EFI_DEVICE_ERROR;
1260 goto exit;
1261 }
1262 }
1263 PortStatusControlReg &= 0xffffffd5;
1264 PortStatusControlReg |= PORTSC_PR;
1265 //
1266 // Set one to PortReset bit must also set zero to PortEnable bit
1267 //
1268 PortStatusControlReg &= ~PORTSC_PED;
1269 break;
1270
1271 case EfiUsbPortPower:
1272
1273 //
1274 // No support, no operation
1275 //
1276 goto exit;
1277
1278 case EfiUsbPortOwner:
1279
1280 PortStatusControlReg &= 0xffffffd5;
1281 PortStatusControlReg |= PORTSC_PO;
1282 break;
1283
1284 default:
1285
1286 Status = EFI_INVALID_PARAMETER;
1287 goto exit;
1288 }
1289
1290 Status = WriteEhcOperationalReg (
1291 HcDev,
1292 PortStatusControlAddr,
1293 PortStatusControlReg
1294 );
1295 if (EFI_ERROR (Status)) {
1296 Status = EFI_DEVICE_ERROR;
1297 }
1298
1299 exit:
1300 return Status;
1301 }
1302
1303 EFI_STATUS
1304 EFIAPI
1305 EhciClearRootHubPortFeature (
1306 IN EFI_USB2_HC_PROTOCOL *This,
1307 IN UINT8 PortNumber,
1308 IN EFI_USB_PORT_FEATURE PortFeature
1309 )
1310 /*++
1311
1312 Routine Description:
1313
1314 Clears a feature for the specified root hub port.
1315
1316 Arguments:
1317
1318 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
1319 PortNumber - Specifies the root hub port whose feature
1320 is requested to be cleared.
1321 PortFeature - Indicates the feature selector associated with the
1322 feature clear request.
1323
1324 Returns:
1325
1326 EFI_SUCCESS
1327 The feature specified by PortFeature was cleared for the
1328 USB root hub port specified by PortNumber.
1329 EFI_INVALID_PARAMETER
1330 PortNumber is invalid or PortFeature is invalid.
1331 EFI_DEVICE_ERROR
1332 Can't read register
1333
1334 --*/
1335 {
1336 EFI_STATUS Status;
1337 USB2_HC_DEV *HcDev;
1338 UINT32 PortStatusControlAddr;
1339 UINT32 PortStatusControlReg;
1340 UINT8 MaxSpeed;
1341 UINT8 TotalPortNumber;
1342 UINT8 Is64BitCapable;
1343
1344 EhciGetCapability (
1345 This,
1346 &MaxSpeed,
1347 &TotalPortNumber,
1348 &Is64BitCapable
1349 );
1350
1351 if (PortNumber >= TotalPortNumber) {
1352 Status = EFI_INVALID_PARAMETER;
1353 goto exit;
1354 }
1355
1356 HcDev = USB2_HC_DEV_FROM_THIS (This);
1357 PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber));
1358
1359 Status = ReadEhcOperationalReg (
1360 HcDev,
1361 PortStatusControlAddr,
1362 &PortStatusControlReg
1363 );
1364 if (EFI_ERROR (Status)) {
1365 Status = EFI_DEVICE_ERROR;
1366 goto exit;
1367 }
1368
1369 switch (PortFeature) {
1370
1371 case EfiUsbPortEnable:
1372
1373 //
1374 // Clear PORT_ENABLE feature means disable port.
1375 //
1376 PortStatusControlReg &= 0xffffffd5;
1377 PortStatusControlReg &= ~PORTSC_PED;
1378 break;
1379
1380 case EfiUsbPortSuspend:
1381
1382 //
1383 // A write of zero to this bit is ignored by the host controller.
1384 // The host controller will unconditionally set this bit to a zero when:
1385 // 1. software sets the Forct Port Resume bit to a zero from a one.
1386 // 2. software sets the Port Reset bit to a one frome a zero.
1387 //
1388 PortStatusControlReg &= 0xffffffd5;
1389 PortStatusControlReg &= ~PORTSC_FPR;
1390 break;
1391
1392 case EfiUsbPortReset:
1393
1394 //
1395 // Clear PORT_RESET means clear the reset signal.
1396 //
1397 PortStatusControlReg &= 0xffffffd5;
1398 PortStatusControlReg &= ~PORTSC_PR;
1399 break;
1400
1401 case EfiUsbPortPower:
1402
1403 //
1404 // No support, no operation
1405 //
1406 goto exit;
1407
1408 case EfiUsbPortOwner:
1409
1410 //
1411 // Clear port owner means this port owned by EHC
1412 //
1413 PortStatusControlReg &= 0xffffffd5;
1414 PortStatusControlReg &= ~PORTSC_PO;
1415 break;
1416
1417 case EfiUsbPortConnectChange:
1418
1419 //
1420 // Clear connect status change
1421 //
1422 PortStatusControlReg &= 0xffffffd5;
1423 PortStatusControlReg |= PORTSC_CSC;
1424 break;
1425
1426 case EfiUsbPortEnableChange:
1427
1428 //
1429 // Clear enable status change
1430 //
1431 PortStatusControlReg &= 0xffffffd5;
1432 PortStatusControlReg |= PORTSC_PEDC;
1433 break;
1434
1435 case EfiUsbPortSuspendChange:
1436
1437 //
1438 // No related bit, no operation
1439 //
1440 goto exit;
1441
1442 case EfiUsbPortOverCurrentChange:
1443
1444 //
1445 // Clear PortOverCurrent change
1446 //
1447 PortStatusControlReg &= 0xffffffd5;
1448 PortStatusControlReg |= PORTSC_OCC;
1449 break;
1450
1451 case EfiUsbPortResetChange:
1452
1453 //
1454 // No related bit, no operation
1455 //
1456 goto exit;
1457
1458 default:
1459
1460 Status = EFI_INVALID_PARAMETER;
1461 goto exit;
1462 }
1463
1464 Status = WriteEhcOperationalReg (
1465 HcDev,
1466 PortStatusControlAddr,
1467 PortStatusControlReg
1468 );
1469 if (EFI_ERROR (Status)) {
1470 Status = EFI_DEVICE_ERROR;
1471 goto exit;
1472 }
1473
1474 exit:
1475 return Status;
1476 }
1477
1478 EFI_STATUS
1479 EFIAPI
1480 EhciControlTransfer (
1481 IN EFI_USB2_HC_PROTOCOL *This,
1482 IN UINT8 DeviceAddress,
1483 IN UINT8 DeviceSpeed,
1484 IN UINTN MaximumPacketLength,
1485 IN EFI_USB_DEVICE_REQUEST *Request,
1486 IN EFI_USB_DATA_DIRECTION TransferDirection,
1487 IN OUT VOID *Data,
1488 IN OUT UINTN *DataLength,
1489 IN UINTN TimeOut,
1490 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
1491 OUT UINT32 *TransferResult
1492 )
1493 /*++
1494
1495 Routine Description:
1496
1497 Submits control transfer to a target USB device.
1498
1499 Arguments:
1500
1501 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
1502 DeviceAddress - Represents the address of the target device on the USB,
1503 which is assigned during USB enumeration.
1504 DeviceSpeed - Indicates target device speed.
1505 MaximumPacketLength - Indicates the maximum packet size that the
1506 default control transfer endpoint is capable of
1507 sending or receiving.
1508 Request - A pointer to the USB device request that will be sent
1509 to the USB device.
1510 TransferDirection - Specifies the data direction for the transfer.
1511 There are three values available, DataIn, DataOut
1512 and NoData.
1513 Data - A pointer to the buffer of data that will be transmitted
1514 to USB device or received from USB device.
1515 DataLength - Indicates the size, in bytes, of the data buffer
1516 specified by Data.
1517 TimeOut - Indicates the maximum time, in microseconds,
1518 which the transfer is allowed to complete.
1519 Translator - A pointr to the transaction translator data.
1520 TransferResult - A pointer to the detailed result information generated
1521 by this control transfer.
1522
1523 Returns:
1524
1525 EFI_SUCCESS
1526 The control transfer was completed successfully.
1527 EFI_OUT_OF_RESOURCES
1528 The control transfer could not be completed due to a lack of resources.
1529 EFI_INVALID_PARAMETER
1530 Some parameters are invalid.
1531 EFI_TIMEOUT
1532 The control transfer failed due to timeout.
1533 EFI_DEVICE_ERROR
1534 The control transfer failed due to host controller or device error.
1535 Caller should check TranferResult for detailed error information.
1536
1537 --*/
1538 {
1539 EFI_STATUS Status;
1540 USB2_HC_DEV *HcDev;
1541 UINT8 PktId;
1542 EHCI_QH_ENTITY *QhPtr;
1543 EHCI_QTD_ENTITY *ControlQtdsPtr;
1544 UINT8 *DataCursor;
1545 VOID *DataMap;
1546 UINT8 *RequestCursor;
1547 VOID *RequestMap;
1548
1549 QhPtr = NULL;
1550 ControlQtdsPtr = NULL;
1551 DataCursor = NULL;
1552 DataMap = NULL;
1553 RequestCursor = NULL;
1554 RequestMap = NULL;
1555 HcDev = USB2_HC_DEV_FROM_THIS (This);
1556
1557 //
1558 // Parameters Checking
1559 //
1560 if (TransferDirection != EfiUsbDataIn &&
1561 TransferDirection != EfiUsbDataOut &&
1562 TransferDirection != EfiUsbNoData
1563 ) {
1564 Status = EFI_INVALID_PARAMETER;
1565 goto exit;
1566 }
1567
1568 if (EfiUsbNoData == TransferDirection) {
1569 if (NULL != Data || 0 != *DataLength) {
1570 Status = EFI_INVALID_PARAMETER;
1571 goto exit;
1572 }
1573 } else {
1574 if (NULL == Data || 0 == *DataLength) {
1575 Status = EFI_INVALID_PARAMETER;
1576 goto exit;
1577 }
1578 }
1579
1580 if (Request == NULL || TransferResult == NULL) {
1581 Status = EFI_INVALID_PARAMETER;
1582 goto exit;
1583 }
1584
1585 if (EFI_USB_SPEED_LOW == DeviceSpeed) {
1586 if (MaximumPacketLength != 8) {
1587 Status = EFI_INVALID_PARAMETER;
1588 goto exit;
1589 }
1590 } else if (MaximumPacketLength != 8 &&
1591 MaximumPacketLength != 16 &&
1592 MaximumPacketLength != 32 &&
1593 MaximumPacketLength != 64
1594 ) {
1595 Status = EFI_INVALID_PARAMETER;
1596 goto exit;
1597 }
1598
1599 //
1600 // If errors exist that cause host controller halt,
1601 // then return EFI_DEVICE_ERROR.
1602 //
1603 if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
1604 ClearEhcAllStatus (HcDev);
1605 *TransferResult = EFI_USB_ERR_SYSTEM;
1606 Status = EFI_DEVICE_ERROR;
1607 goto exit;
1608 }
1609
1610 //
1611 // Map the Request for bus master access.
1612 // BusMasterRead means cpu write
1613 //
1614 Status = MapRequestBuffer (
1615 HcDev,
1616 Request,
1617 &RequestCursor,
1618 &RequestMap
1619 );
1620 if (EFI_ERROR (Status)) {
1621 *TransferResult = EFI_USB_ERR_SYSTEM;
1622 Status = EFI_DEVICE_ERROR;
1623 goto exit;
1624 }
1625
1626 //
1627 // Map the source data buffer for bus master access.
1628 //
1629 Status = MapDataBuffer (
1630 HcDev,
1631 TransferDirection,
1632 Data,
1633 DataLength,
1634 &PktId,
1635 &DataCursor,
1636 &DataMap
1637 );
1638 if (EFI_ERROR (Status)) {
1639 *TransferResult = EFI_USB_ERR_SYSTEM;
1640 Status = EFI_DEVICE_ERROR;
1641 goto unmap_request;
1642 }
1643
1644 //
1645 // Create and init control Qh
1646 //
1647 Status = CreateControlQh (
1648 HcDev,
1649 DeviceAddress,
1650 DeviceSpeed,
1651 MaximumPacketLength,
1652 Translator,
1653 &QhPtr
1654 );
1655 if (EFI_ERROR (Status)) {
1656 *TransferResult = EFI_USB_ERR_SYSTEM;
1657 Status = EFI_OUT_OF_RESOURCES;
1658 goto unmap_data;
1659 }
1660
1661 //
1662 // Create and init control Qtds
1663 //
1664 Status = CreateControlQtds (
1665 HcDev,
1666 PktId,
1667 RequestCursor,
1668 DataCursor,
1669 *DataLength,
1670 Translator,
1671 &ControlQtdsPtr
1672 );
1673 if (EFI_ERROR (Status)) {
1674 *TransferResult = EFI_USB_ERR_SYSTEM;
1675 Status = EFI_OUT_OF_RESOURCES;
1676 goto destory_qh;
1677 }
1678
1679 //
1680 // Link Qtds to Qh
1681 //
1682 LinkQtdToQh (QhPtr, ControlQtdsPtr);
1683
1684 ClearEhcAllStatus (HcDev);
1685
1686 //
1687 // Link Qh and Qtds to Async Schedule List
1688 //
1689 Status = LinkQhToAsyncList (HcDev, QhPtr);
1690 if (EFI_ERROR (Status)) {
1691 *TransferResult = EFI_USB_ERR_SYSTEM;
1692 Status = EFI_DEVICE_ERROR;
1693 goto destory_qtds;
1694 }
1695
1696 //
1697 // Poll Qh-Qtds execution and get result.
1698 // detail status is returned
1699 //
1700 Status = ExecuteTransfer (
1701 HcDev,
1702 TRUE,
1703 QhPtr,
1704 DataLength,
1705 0,
1706 TimeOut,
1707 TransferResult
1708 );
1709 if (EFI_ERROR (Status)) {
1710 goto destory_qtds;
1711 }
1712
1713 //
1714 // If has errors that cause host controller halt,
1715 // then return EFI_DEVICE_ERROR directly.
1716 //
1717 if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
1718 *TransferResult |= EFI_USB_ERR_SYSTEM;
1719 }
1720
1721 ClearEhcAllStatus (HcDev);
1722
1723 destory_qtds:
1724 UnlinkQhFromAsyncList (HcDev, QhPtr);
1725 DestoryQtds (HcDev, ControlQtdsPtr);
1726 destory_qh:
1727 DestoryQh (HcDev, QhPtr);
1728 unmap_data:
1729 HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
1730 unmap_request:
1731 HcDev->PciIo->Unmap (HcDev->PciIo, RequestMap);
1732 exit:
1733 HcDev->PciIo->Flush (HcDev->PciIo);
1734 return Status;
1735 }
1736
1737 EFI_STATUS
1738 EFIAPI
1739 EhciBulkTransfer (
1740 IN EFI_USB2_HC_PROTOCOL *This,
1741 IN UINT8 DeviceAddress,
1742 IN UINT8 EndPointAddress,
1743 IN UINT8 DeviceSpeed,
1744 IN UINTN MaximumPacketLength,
1745 IN UINT8 DataBuffersNumber,
1746 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
1747 IN OUT UINTN *DataLength,
1748 IN OUT UINT8 *DataToggle,
1749 IN UINTN TimeOut,
1750 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
1751 OUT UINT32 *TransferResult
1752 )
1753 /*++
1754
1755 Routine Description:
1756
1757 Submits bulk transfer to a bulk endpoint of a USB device.
1758
1759 Arguments:
1760
1761 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
1762 DeviceAddress - Represents the address of the target device on the USB,
1763 which is assigned during USB enumeration.
1764 EndPointAddress - The combination of an endpoint number and an
1765 endpoint direction of the target USB device.
1766 Each endpoint address supports data transfer in
1767 one direction except the control endpoint
1768 (whose default endpoint address is 0).
1769 It is the caller's responsibility to make sure that
1770 the EndPointAddress represents a bulk endpoint.
1771 DeviceSpeed - Indicates device speed. The supported values are EFI_USB_SPEED_FULL
1772 and EFI_USB_SPEED_HIGH.
1773 MaximumPacketLength - Indicates the maximum packet size the target endpoint
1774 is capable of sending or receiving.
1775 DataBuffersNumber - Number of data buffers prepared for the transfer.
1776 Data - Array of pointers to the buffers of data that will be transmitted
1777 to USB device or received from USB device.
1778 DataLength - When input, indicates the size, in bytes, of the data buffer
1779 specified by Data. When output, indicates the actually
1780 transferred data size.
1781 DataToggle - A pointer to the data toggle value. On input, it indicates
1782 the initial data toggle value the bulk transfer should adopt;
1783 on output, it is updated to indicate the data toggle value
1784 of the subsequent bulk transfer.
1785 Translator - A pointr to the transaction translator data.
1786 TimeOut - Indicates the maximum time, in microseconds, which the
1787 transfer is allowed to complete.
1788 TransferResult - A pointer to the detailed result information of the
1789 bulk transfer.
1790
1791 Returns:
1792
1793 EFI_SUCCESS
1794 The bulk transfer was completed successfully.
1795 EFI_OUT_OF_RESOURCES
1796 The bulk transfer could not be submitted due to lack of resource.
1797 EFI_INVALID_PARAMETER
1798 Some parameters are invalid.
1799 EFI_TIMEOUT
1800 The bulk transfer failed due to timeout.
1801 EFI_DEVICE_ERROR
1802 The bulk transfer failed due to host controller or device error.
1803 Caller should check TranferResult for detailed error information.
1804
1805 --*/
1806 {
1807 EFI_STATUS Status;
1808 USB2_HC_DEV *HcDev;
1809 UINT8 PktId;
1810 EHCI_QH_ENTITY *QhPtr;
1811 EHCI_QTD_ENTITY *BulkQtdsPtr;
1812 UINT8 *DataCursor;
1813 VOID *DataMap;
1814 EFI_USB_DATA_DIRECTION TransferDirection;
1815
1816 QhPtr = NULL;
1817 BulkQtdsPtr = NULL;
1818 DataCursor = NULL;
1819 DataMap = NULL;
1820 HcDev = USB2_HC_DEV_FROM_THIS (This);
1821
1822 //
1823 // Parameters Checking
1824 //
1825 if (NULL == DataLength ||
1826 NULL == Data ||
1827 NULL == Data[0] ||
1828 NULL == TransferResult
1829 ) {
1830 Status = EFI_INVALID_PARAMETER;
1831 goto exit;
1832 }
1833
1834 if (*DataLength == 0) {
1835 Status = EFI_INVALID_PARAMETER;
1836 goto exit;
1837 }
1838
1839 if (1 != *DataToggle && 0 != *DataToggle) {
1840 Status = EFI_INVALID_PARAMETER;
1841 goto exit;
1842 }
1843
1844 if (EFI_USB_SPEED_LOW == DeviceSpeed) {
1845 Status = EFI_INVALID_PARAMETER;
1846 goto exit;
1847 }
1848
1849 if (EFI_USB_SPEED_FULL == DeviceSpeed) {
1850 if (MaximumPacketLength > 64) {
1851 Status = EFI_INVALID_PARAMETER;
1852 goto exit;
1853 }
1854 }
1855
1856 if (EFI_USB_SPEED_HIGH == DeviceSpeed) {
1857 if (MaximumPacketLength > 512) {
1858 Status = EFI_INVALID_PARAMETER;
1859 goto exit;
1860 }
1861 }
1862
1863 //
1864 // if has errors that cause host controller halt,
1865 // then return EFI_DEVICE_ERROR directly.
1866 //
1867 if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
1868 ClearEhcAllStatus (HcDev);
1869 *TransferResult = EFI_USB_ERR_SYSTEM;
1870 Status = EFI_DEVICE_ERROR;
1871 goto exit;
1872 }
1873
1874 Status = ClearEhcAllStatus (HcDev);
1875 if (EFI_ERROR (Status)) {
1876 Status = EFI_DEVICE_ERROR;
1877 goto exit;
1878 }
1879
1880 //
1881 // construct QH and TD data structures,
1882 // and link them together
1883 //
1884 if (EndPointAddress & 0x80) {
1885 TransferDirection = EfiUsbDataIn;
1886 } else {
1887 TransferDirection = EfiUsbDataOut;
1888 }
1889
1890 Status = MapDataBuffer (
1891 HcDev,
1892 TransferDirection,
1893 Data[0],
1894 DataLength,
1895 &PktId,
1896 &DataCursor,
1897 &DataMap
1898 );
1899 if (EFI_ERROR (Status)) {
1900 *TransferResult = EFI_USB_ERR_SYSTEM;
1901 Status = EFI_DEVICE_ERROR;
1902 goto exit;
1903 }
1904
1905 //
1906 // Create and init Bulk Qh
1907 //
1908 Status = CreateBulkQh (
1909 HcDev,
1910 DeviceAddress,
1911 EndPointAddress,
1912 DeviceSpeed,
1913 *DataToggle,
1914 MaximumPacketLength,
1915 Translator,
1916 &QhPtr
1917 );
1918 if (EFI_ERROR (Status)) {
1919 *TransferResult = EFI_USB_ERR_SYSTEM;
1920 Status = EFI_OUT_OF_RESOURCES;
1921 goto unmap_data;
1922 }
1923
1924 //
1925 // Create and init Bulk Qtds
1926 //
1927 Status = CreateBulkOrInterruptQtds (
1928 HcDev,
1929 PktId,
1930 DataCursor,
1931 *DataLength,
1932 Translator,
1933 &BulkQtdsPtr
1934 );
1935 if (EFI_ERROR (Status)) {
1936 *TransferResult = EFI_USB_ERR_SYSTEM;
1937 Status = EFI_OUT_OF_RESOURCES;
1938 goto destory_qh;
1939 }
1940
1941 //
1942 // Link Qtds to Qh
1943 //
1944 LinkQtdToQh (QhPtr, BulkQtdsPtr);
1945
1946 ClearEhcAllStatus (HcDev);
1947
1948 //
1949 // Link Qh and qtds to Async Schedule List
1950 //
1951 Status = LinkQhToAsyncList (HcDev, QhPtr);
1952 if (EFI_ERROR (Status)) {
1953 *TransferResult = EFI_USB_ERR_SYSTEM;
1954 Status = EFI_DEVICE_ERROR;
1955 goto destory_qtds;
1956 }
1957
1958 //
1959 // Poll QH-TDs execution and get result.
1960 // detail status is returned
1961 //
1962 Status = ExecuteTransfer (
1963 HcDev,
1964 FALSE,
1965 QhPtr,
1966 DataLength,
1967 DataToggle,
1968 TimeOut,
1969 TransferResult
1970 );
1971 if (EFI_ERROR (Status)) {
1972 goto destory_qtds;
1973 }
1974
1975 //
1976 // if has errors that cause host controller halt,
1977 // then return EFI_DEVICE_ERROR directly.
1978 //
1979 if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
1980 *TransferResult |= EFI_USB_ERR_SYSTEM;
1981 }
1982
1983 ClearEhcAllStatus (HcDev);
1984
1985 destory_qtds:
1986 UnlinkQhFromAsyncList (HcDev, QhPtr);
1987 DestoryQtds (HcDev, BulkQtdsPtr);
1988 destory_qh:
1989 DestoryQh (HcDev, QhPtr);
1990 unmap_data:
1991 HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
1992 exit:
1993 HcDev->PciIo->Flush (HcDev->PciIo);
1994 return Status;
1995 }
1996
1997 EFI_STATUS
1998 EFIAPI
1999 EhciAsyncInterruptTransfer (
2000 IN EFI_USB2_HC_PROTOCOL * This,
2001 IN UINT8 DeviceAddress,
2002 IN UINT8 EndPointAddress,
2003 IN UINT8 DeviceSpeed,
2004 IN UINTN MaximumPacketLength,
2005 IN BOOLEAN IsNewTransfer,
2006 IN OUT UINT8 *DataToggle,
2007 IN UINTN PollingInterval,
2008 IN UINTN DataLength,
2009 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,
2010 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
2011 IN VOID *Context OPTIONAL
2012 )
2013 /*++
2014
2015 Routine Description:
2016
2017 Submits an asynchronous interrupt transfer to an
2018 interrupt endpoint of a USB device.
2019 Translator parameter doesn't exist in UEFI2.0 spec, but it will be updated
2020 in the following specification version.
2021
2022 Arguments:
2023
2024 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
2025 DeviceAddress - Represents the address of the target device on the USB,
2026 which is assigned during USB enumeration.
2027 EndPointAddress - The combination of an endpoint number and an endpoint
2028 direction of the target USB device. Each endpoint address
2029 supports data transfer in one direction except the
2030 control endpoint (whose default endpoint address is 0).
2031 It is the caller's responsibility to make sure that
2032 the EndPointAddress represents an interrupt endpoint.
2033 DeviceSpeed - Indicates device speed.
2034 MaximumPacketLength - Indicates the maximum packet size the target endpoint
2035 is capable of sending or receiving.
2036 IsNewTransfer - If TRUE, an asynchronous interrupt pipe is built between
2037 the host and the target interrupt endpoint.
2038 If FALSE, the specified asynchronous interrupt pipe
2039 is canceled.
2040 DataToggle - A pointer to the data toggle value. On input, it is valid
2041 when IsNewTransfer is TRUE, and it indicates the initial
2042 data toggle value the asynchronous interrupt transfer
2043 should adopt.
2044 On output, it is valid when IsNewTransfer is FALSE,
2045 and it is updated to indicate the data toggle value of
2046 the subsequent asynchronous interrupt transfer.
2047 PollingInterval - Indicates the interval, in milliseconds, that the
2048 asynchronous interrupt transfer is polled.
2049 This parameter is required when IsNewTransfer is TRUE.
2050 DataLength - Indicates the length of data to be received at the
2051 rate specified by PollingInterval from the target
2052 asynchronous interrupt endpoint. This parameter
2053 is only required when IsNewTransfer is TRUE.
2054 Translator - A pointr to the transaction translator data.
2055 CallBackFunction - The Callback function.This function is called at the
2056 rate specified by PollingInterval.This parameter is
2057 only required when IsNewTransfer is TRUE.
2058 Context - The context that is passed to the CallBackFunction.
2059 - This is an optional parameter and may be NULL.
2060
2061 Returns:
2062
2063 EFI_SUCCESS
2064 The asynchronous interrupt transfer request has been successfully
2065 submitted or canceled.
2066 EFI_INVALID_PARAMETER
2067 Some parameters are invalid.
2068 EFI_OUT_OF_RESOURCES
2069 The request could not be completed due to a lack of resources.
2070 EFI_DEVICE_ERROR
2071 Can't read register
2072
2073 --*/
2074 {
2075 EFI_STATUS Status;
2076 USB2_HC_DEV *HcDev;
2077 UINT8 PktId;
2078 EHCI_QH_ENTITY *QhPtr;
2079 EHCI_QTD_ENTITY *InterruptQtdsPtr;
2080 UINT8 *DataPtr;
2081 UINT8 *DataCursor;
2082 VOID *DataMap;
2083 UINTN MappedLength;
2084 EHCI_ASYNC_REQUEST *AsyncRequestPtr;
2085 EFI_TPL OldTpl;
2086
2087 QhPtr = NULL;
2088 InterruptQtdsPtr = NULL;
2089 DataPtr = NULL;
2090 DataCursor = NULL;
2091 DataMap = NULL;
2092 AsyncRequestPtr = NULL;
2093 HcDev = USB2_HC_DEV_FROM_THIS (This);
2094
2095 //
2096 // Parameters Checking
2097 //
2098 if (!IsDataInTransfer (EndPointAddress)) {
2099 Status = EFI_INVALID_PARAMETER;
2100 goto exit;
2101 }
2102
2103 if (IsNewTransfer) {
2104 if (0 == DataLength) {
2105 Status = EFI_INVALID_PARAMETER;
2106 goto exit;
2107 }
2108
2109 if (*DataToggle != 1 && *DataToggle != 0) {
2110 Status = EFI_INVALID_PARAMETER;
2111 goto exit;
2112 }
2113
2114 if (PollingInterval > 255 || PollingInterval < 1) {
2115 Status = EFI_INVALID_PARAMETER;
2116 goto exit;
2117 }
2118 }
2119
2120 //
2121 // if has errors that cause host controller halt,
2122 // then return EFI_DEVICE_ERROR directly.
2123 //
2124 if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
2125 ClearEhcAllStatus (HcDev);
2126 Status = EFI_DEVICE_ERROR;
2127 goto exit;
2128 }
2129
2130 Status = ClearEhcAllStatus (HcDev);
2131 if (EFI_ERROR (Status)) {
2132 Status = EFI_DEVICE_ERROR;
2133 goto exit;
2134 }
2135
2136 //
2137 // Delete Async interrupt transfer request
2138 //
2139 if (!IsNewTransfer) {
2140
2141 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
2142
2143 Status = DeleteAsyncRequestTransfer (
2144 HcDev,
2145 DeviceAddress,
2146 EndPointAddress,
2147 DataToggle
2148 );
2149
2150 gBS->RestoreTPL (OldTpl);
2151
2152 goto exit;
2153 }
2154
2155 Status = EhciAllocatePool (
2156 HcDev,
2157 (UINT8 **) &AsyncRequestPtr,
2158 sizeof (EHCI_ASYNC_REQUEST)
2159 );
2160 if (EFI_ERROR (Status)) {
2161 Status = EFI_OUT_OF_RESOURCES;
2162 goto exit;
2163 }
2164
2165 Status = EhciAllocatePool (HcDev, &DataPtr, DataLength);
2166 if (EFI_ERROR (Status)) {
2167 Status = EFI_OUT_OF_RESOURCES;
2168 goto free_request;
2169 }
2170
2171 MappedLength = DataLength;
2172 Status = MapDataBuffer (
2173 HcDev,
2174 EfiUsbDataIn,
2175 DataPtr,
2176 &MappedLength,
2177 &PktId,
2178 &DataCursor,
2179 &DataMap
2180 );
2181 if (EFI_ERROR (Status)) {
2182 Status = EFI_DEVICE_ERROR;
2183 goto free_data;
2184 }
2185
2186 //
2187 // Create and init Interrupt Qh
2188 //
2189 Status = CreateInterruptQh (
2190 HcDev,
2191 DeviceAddress,
2192 EndPointAddress,
2193 DeviceSpeed,
2194 *DataToggle,
2195 MaximumPacketLength,
2196 PollingInterval,
2197 Translator,
2198 &QhPtr
2199 );
2200 if (EFI_ERROR (Status)) {
2201 Status = EFI_OUT_OF_RESOURCES;
2202 goto unmap_data;
2203 }
2204
2205 //
2206 // Create and init Interrupt Qtds
2207 //
2208 Status = CreateBulkOrInterruptQtds (
2209 HcDev,
2210 PktId,
2211 DataCursor,
2212 MappedLength,
2213 Translator,
2214 &InterruptQtdsPtr
2215 );
2216 if (EFI_ERROR (Status)) {
2217 Status = EFI_OUT_OF_RESOURCES;
2218 goto destory_qh;
2219 }
2220
2221 //
2222 // Link Qtds to Qh
2223 //
2224 LinkQtdToQh (QhPtr, InterruptQtdsPtr);
2225
2226 //
2227 // Init AsyncRequest Entry
2228 //
2229 AsyncRequestPtr->Context = Context;
2230 AsyncRequestPtr->CallBackFunc = CallBackFunction;
2231 AsyncRequestPtr->TransferType = ASYNC_INTERRUPT_TRANSFER;
2232 AsyncRequestPtr->QhPtr = QhPtr;
2233 AsyncRequestPtr->Prev = NULL;
2234 AsyncRequestPtr->Next = NULL;
2235
2236 if (NULL == HcDev->AsyncRequestList) {
2237 Status = StartPollingTimer (HcDev);
2238 if (EFI_ERROR (Status)) {
2239 Status = EFI_DEVICE_ERROR;
2240 CleanUpAllAsyncRequestTransfer (HcDev);
2241 goto exit;
2242 }
2243 }
2244
2245 //
2246 // Link Entry to AsyncRequest List
2247 //
2248 LinkToAsyncReqeust (HcDev, AsyncRequestPtr);
2249
2250 ClearEhcAllStatus (HcDev);
2251
2252 Status = DisablePeriodicSchedule (HcDev);
2253 if (EFI_ERROR (Status)) {
2254 Status = EFI_DEVICE_ERROR;
2255 goto exit;
2256 }
2257
2258 Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
2259 if (EFI_ERROR (Status)) {
2260 Status = EFI_TIMEOUT;
2261 goto exit;
2262 }
2263
2264 //
2265 // Link Qh and Qtds to Periodic Schedule List
2266 //
2267 LinkQhToPeriodicList (HcDev, QhPtr);
2268
2269 Status = EnablePeriodicSchedule (HcDev);
2270 if (EFI_ERROR (Status)) {
2271 Status = EFI_DEVICE_ERROR;
2272 goto exit;
2273 }
2274
2275 Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
2276 if (EFI_ERROR (Status)) {
2277 Status = EFI_TIMEOUT;
2278 goto exit;
2279 }
2280
2281 if (IsEhcHalted (HcDev)) {
2282 Status = StartScheduleExecution (HcDev);
2283 if (EFI_ERROR (Status)) {
2284 Status = EFI_DEVICE_ERROR;
2285 goto exit;
2286 }
2287 }
2288
2289 HcDev->PciIo->Flush (HcDev->PciIo);
2290 goto exit;
2291
2292 destory_qh:
2293 DestoryQh (HcDev, QhPtr);
2294 free_data:
2295 EhciFreePool (HcDev, DataPtr, DataLength);
2296 free_request:
2297 EhciFreePool (
2298 HcDev,
2299 (UINT8 *) AsyncRequestPtr,
2300 sizeof (EHCI_ASYNC_REQUEST)
2301 );
2302 unmap_data:
2303 HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
2304 exit:
2305 return Status;
2306 }
2307
2308 EFI_STATUS
2309 EFIAPI
2310 EhciSyncInterruptTransfer (
2311 IN EFI_USB2_HC_PROTOCOL *This,
2312 IN UINT8 DeviceAddress,
2313 IN UINT8 EndPointAddress,
2314 IN UINT8 DeviceSpeed,
2315 IN UINTN MaximumPacketLength,
2316 IN OUT VOID *Data,
2317 IN OUT UINTN *DataLength,
2318 IN OUT UINT8 *DataToggle,
2319 IN UINTN TimeOut,
2320 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
2321 OUT UINT32 *TransferResult
2322 )
2323 /*++
2324
2325 Routine Description:
2326
2327 Submits synchronous interrupt transfer to an interrupt endpoint
2328 of a USB device.
2329 Translator parameter doesn't exist in UEFI2.0 spec, but it will be updated
2330 in the following specification version.
2331
2332 Arguments:
2333
2334 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
2335 DeviceAddress - Represents the address of the target device on the USB,
2336 which is assigned during USB enumeration.
2337 EndPointAddress - The combination of an endpoint number and an endpoint
2338 direction of the target USB device. Each endpoint
2339 address supports data transfer in one direction
2340 except the control endpoint (whose default
2341 endpoint address is 0). It is the caller's responsibility
2342 to make sure that the EndPointAddress represents
2343 an interrupt endpoint.
2344 DeviceSpeed - Indicates device speed.
2345 MaximumPacketLength - Indicates the maximum packet size the target endpoint
2346 is capable of sending or receiving.
2347 Data - A pointer to the buffer of data that will be transmitted
2348 to USB device or received from USB device.
2349 DataLength - On input, the size, in bytes, of the data buffer specified
2350 by Data. On output, the number of bytes transferred.
2351 DataToggle - A pointer to the data toggle value. On input, it indicates
2352 the initial data toggle value the synchronous interrupt
2353 transfer should adopt;
2354 on output, it is updated to indicate the data toggle value
2355 of the subsequent synchronous interrupt transfer.
2356 TimeOut - Indicates the maximum time, in microseconds, which the
2357 transfer is allowed to complete.
2358 Translator - A pointr to the transaction translator data.
2359 TransferResult - A pointer to the detailed result information from
2360 the synchronous interrupt transfer.
2361
2362 Returns:
2363
2364 EFI_SUCCESS
2365 The synchronous interrupt transfer was completed successfully.
2366 EFI_OUT_OF_RESOURCES
2367 The synchronous interrupt transfer could not be submitted due
2368 to lack of resource.
2369 EFI_INVALID_PARAMETER
2370 Some parameters are invalid.
2371 EFI_TIMEOUT
2372 The synchronous interrupt transfer failed due to timeout.
2373 EFI_DEVICE_ERROR
2374 The synchronous interrupt transfer failed due to host controller
2375 or device error. Caller should check TranferResult for detailed
2376 error information.
2377
2378 --*/
2379 {
2380 EFI_STATUS Status;
2381 USB2_HC_DEV *HcDev;
2382 UINT8 PktId;
2383 EHCI_QH_ENTITY *QhPtr;
2384 EHCI_QTD_ENTITY *InterruptQtdsPtr;
2385 UINT8 *DataCursor;
2386 VOID *DataMap;
2387
2388 QhPtr = NULL;
2389 InterruptQtdsPtr = NULL;
2390 DataCursor = NULL;
2391 DataMap = NULL;
2392 HcDev = USB2_HC_DEV_FROM_THIS (This);
2393
2394 //
2395 // Parameters Checking
2396 //
2397 if (DataLength == NULL ||
2398 Data == NULL ||
2399 TransferResult == NULL
2400 ) {
2401 Status = EFI_INVALID_PARAMETER;
2402 goto exit;
2403 }
2404
2405 if (!IsDataInTransfer (EndPointAddress)) {
2406 Status = EFI_INVALID_PARAMETER;
2407 goto exit;
2408 }
2409
2410 if (0 == *DataLength) {
2411 Status = EFI_INVALID_PARAMETER;
2412 goto exit;
2413 }
2414
2415 if (*DataToggle != 1 && *DataToggle != 0) {
2416 Status = EFI_INVALID_PARAMETER;
2417 goto exit;
2418 }
2419
2420 if (EFI_USB_SPEED_LOW == DeviceSpeed && 8 != MaximumPacketLength) {
2421 Status = EFI_INVALID_PARAMETER;
2422 goto exit;
2423 }
2424
2425 if (EFI_USB_SPEED_FULL == DeviceSpeed && MaximumPacketLength > 64) {
2426 Status = EFI_INVALID_PARAMETER;
2427 goto exit;
2428 }
2429
2430 if (EFI_USB_SPEED_HIGH == DeviceSpeed && MaximumPacketLength > 3072) {
2431 Status = EFI_INVALID_PARAMETER;
2432 goto exit;
2433 }
2434
2435 //
2436 // if has errors that cause host controller halt,
2437 // then return EFI_DEVICE_ERROR directly.
2438 //
2439 if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
2440 ClearEhcAllStatus (HcDev);
2441 *TransferResult = EFI_USB_ERR_SYSTEM;
2442 Status = EFI_DEVICE_ERROR;
2443 goto exit;
2444 }
2445
2446 Status = ClearEhcAllStatus (HcDev);
2447 if (EFI_ERROR (Status)) {
2448 Status = EFI_DEVICE_ERROR;
2449 goto exit;
2450 }
2451
2452 Status = MapDataBuffer (
2453 HcDev,
2454 EfiUsbDataIn,
2455 Data,
2456 DataLength,
2457 &PktId,
2458 &DataCursor,
2459 &DataMap
2460 );
2461 if (EFI_ERROR (Status)) {
2462 *TransferResult = EFI_USB_ERR_SYSTEM;
2463 Status = EFI_DEVICE_ERROR;
2464 goto exit;
2465 }
2466
2467 //
2468 // Create and init Interrupt Qh
2469 //
2470 Status = CreateInterruptQh (
2471 HcDev,
2472 DeviceAddress,
2473 EndPointAddress,
2474 DeviceSpeed,
2475 *DataToggle,
2476 MaximumPacketLength,
2477 0,
2478 Translator,
2479 &QhPtr
2480 );
2481 if (EFI_ERROR (Status)) {
2482 Status = EFI_OUT_OF_RESOURCES;
2483 goto unmap_data;
2484 }
2485
2486 //
2487 // Create and init Interrupt Qtds
2488 //
2489 Status = CreateBulkOrInterruptQtds (
2490 HcDev,
2491 PktId,
2492 DataCursor,
2493 *DataLength,
2494 Translator,
2495 &InterruptQtdsPtr
2496 );
2497 if (EFI_ERROR (Status)) {
2498 *TransferResult = EFI_USB_ERR_SYSTEM;
2499 Status = EFI_OUT_OF_RESOURCES;
2500 goto destory_qh;
2501 }
2502
2503 //
2504 // Link Qtds to Qh
2505 //
2506 LinkQtdToQh (QhPtr, InterruptQtdsPtr);
2507
2508 ClearEhcAllStatus (HcDev);
2509
2510 Status = DisablePeriodicSchedule (HcDev);
2511 if (EFI_ERROR (Status)) {
2512 Status = EFI_DEVICE_ERROR;
2513 goto exit;
2514 }
2515
2516 Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
2517 if (EFI_ERROR (Status)) {
2518 Status = EFI_TIMEOUT;
2519 goto exit;
2520 }
2521
2522 //
2523 // Link Qh and Qtds to Periodic Schedule List
2524 //
2525 LinkQhToPeriodicList (HcDev, QhPtr);
2526
2527 Status = EnablePeriodicSchedule (HcDev);
2528 if (EFI_ERROR (Status)) {
2529 Status = EFI_DEVICE_ERROR;
2530 goto exit;
2531 }
2532
2533 Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
2534 if (EFI_ERROR (Status)) {
2535 Status = EFI_TIMEOUT;
2536 goto exit;
2537 }
2538
2539 if (IsEhcHalted (HcDev)) {
2540 Status = StartScheduleExecution (HcDev);
2541 if (EFI_ERROR (Status)) {
2542 Status = EFI_DEVICE_ERROR;
2543 goto exit;
2544 }
2545 }
2546
2547 //
2548 // Poll QH-TDs execution and get result.
2549 // detail status is returned
2550 //
2551 Status = ExecuteTransfer (
2552 HcDev,
2553 FALSE,
2554 QhPtr,
2555 DataLength,
2556 DataToggle,
2557 TimeOut,
2558 TransferResult
2559 );
2560 if (EFI_ERROR (Status)) {
2561 goto destory_qtds;
2562 }
2563
2564 //
2565 // if has errors that cause host controller halt,
2566 // then return EFI_DEVICE_ERROR directly.
2567 //
2568 if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
2569 *TransferResult |= EFI_USB_ERR_SYSTEM;
2570 }
2571
2572 ClearEhcAllStatus (HcDev);
2573
2574 destory_qtds:
2575 UnlinkQhFromPeriodicList (HcDev, QhPtr, 0);
2576 DestoryQtds (HcDev, InterruptQtdsPtr);
2577 destory_qh:
2578 DestoryQh (HcDev, QhPtr);
2579 unmap_data:
2580 HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
2581 exit:
2582 HcDev->PciIo->Flush (HcDev->PciIo);
2583 return Status;
2584 }
2585
2586 EFI_STATUS
2587 EFIAPI
2588 EhciIsochronousTransfer (
2589 IN EFI_USB2_HC_PROTOCOL *This,
2590 IN UINT8 DeviceAddress,
2591 IN UINT8 EndPointAddress,
2592 IN UINT8 DeviceSpeed,
2593 IN UINTN MaximumPacketLength,
2594 IN UINT8 DataBuffersNumber,
2595 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
2596 IN UINTN DataLength,
2597 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
2598 OUT UINT32 *TransferResult
2599 )
2600 /*++
2601
2602 Routine Description:
2603
2604 Submits isochronous transfer to a target USB device.
2605
2606 Arguments:
2607
2608 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
2609 DeviceAddress - Represents the address of the target device on the USB,
2610 which is assigned during USB enumeration.
2611 EndPointAddress - End point address
2612 DeviceSpeed - Indicates device speed.
2613 MaximumPacketLength - Indicates the maximum packet size that the
2614 default control transfer endpoint is capable of
2615 sending or receiving.
2616 DataBuffersNumber - Number of data buffers prepared for the transfer.
2617 Data - Array of pointers to the buffers of data that will be
2618 transmitted to USB device or received from USB device.
2619 DataLength - Indicates the size, in bytes, of the data buffer
2620 specified by Data.
2621 Translator - A pointr to the transaction translator data.
2622 TransferResult - A pointer to the detailed result information generated
2623 by this control transfer.
2624
2625 Returns:
2626
2627 EFI_UNSUPPORTED
2628
2629 --*/
2630 {
2631 return EFI_UNSUPPORTED;
2632 }
2633
2634 EFI_STATUS
2635 EFIAPI
2636 EhciAsyncIsochronousTransfer (
2637 IN EFI_USB2_HC_PROTOCOL *This,
2638 IN UINT8 DeviceAddress,
2639 IN UINT8 EndPointAddress,
2640 IN UINT8 DeviceSpeed,
2641 IN UINTN MaximumPacketLength,
2642 IN UINT8 DataBuffersNumber,
2643 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
2644 IN UINTN DataLength,
2645 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
2646 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
2647 IN VOID *Context
2648 )
2649 /*++
2650
2651 Routine Description:
2652
2653 Submits Async isochronous transfer to a target USB device.
2654
2655 Arguments:
2656
2657 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
2658 DeviceAddress - Represents the address of the target device on the USB,
2659 which is assigned during USB enumeration.
2660 EndPointAddress - End point address
2661 DeviceSpeed - Indicates device speed.
2662 MaximumPacketLength - Indicates the maximum packet size that the
2663 default control transfer endpoint is capable of
2664 sending or receiving.
2665 DataBuffersNumber - Number of data buffers prepared for the transfer.
2666 Data - Array of pointers to the buffers of data that will be transmitted
2667 to USB device or received from USB device.
2668 Translator - A pointr to the transaction translator data.
2669 IsochronousCallBack - When the transfer complete, the call back function will be called
2670 Context - Pass to the call back function as parameter
2671
2672 Returns:
2673
2674 EFI_UNSUPPORTED
2675
2676 --*/
2677 {
2678 return EFI_UNSUPPORTED;
2679 }