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