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