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