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