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