e7d359ee2495e8137e751daf2c05027faf603274
[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
2166 Arguments:
2167
2168 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
2169 DeviceAddress - Represents the address of the target device on the USB,
2170 which is assigned during USB enumeration.
2171 EndPointAddress - The combination of an endpoint number and an endpoint
2172 direction of the target USB device. Each endpoint address
2173 supports data transfer in one direction except the
2174 control endpoint (whose default endpoint address is 0).
2175 It is the caller's responsibility to make sure that
2176 the EndPointAddress represents an interrupt endpoint.
2177 DeviceSpeed - Indicates device speed.
2178 MaximumPacketLength - Indicates the maximum packet size the target endpoint
2179 is capable of sending or receiving.
2180 IsNewTransfer - If TRUE, an asynchronous interrupt pipe is built between
2181 the host and the target interrupt endpoint.
2182 If FALSE, the specified asynchronous interrupt pipe
2183 is canceled.
2184 DataToggle - A pointer to the data toggle value. On input, it is valid
2185 when IsNewTransfer is TRUE, and it indicates the initial
2186 data toggle value the asynchronous interrupt transfer
2187 should adopt.
2188 On output, it is valid when IsNewTransfer is FALSE,
2189 and it is updated to indicate the data toggle value of
2190 the subsequent asynchronous interrupt transfer.
2191 PollingInterval - Indicates the interval, in milliseconds, that the
2192 asynchronous interrupt transfer is polled.
2193 This parameter is required when IsNewTransfer is TRUE.
2194 DataLength - Indicates the length of data to be received at the
2195 rate specified by PollingInterval from the target
2196 asynchronous interrupt endpoint. This parameter
2197 is only required when IsNewTransfer is TRUE.
2198 Translator - A pointr to the transaction translator data.
2199 CallBackFunction - The Callback function.This function is called at the
2200 rate specified by PollingInterval.This parameter is
2201 only required when IsNewTransfer is TRUE.
2202 Context - The context that is passed to the CallBackFunction.
2203 - This is an optional parameter and may be NULL.
2204
2205 Returns:
2206
2207 EFI_SUCCESS
2208 The asynchronous interrupt transfer request has been successfully
2209 submitted or canceled.
2210 EFI_INVALID_PARAMETER
2211 Some parameters are invalid.
2212 EFI_OUT_OF_RESOURCES
2213 The request could not be completed due to a lack of resources.
2214 EFI_DEVICE_ERROR
2215 Can't read register
2216
2217 --*/
2218 {
2219 EFI_STATUS Status;
2220 USB2_HC_DEV *HcDev;
2221 UINT8 PktId;
2222 EHCI_QH_ENTITY *QhPtr;
2223 EHCI_QTD_ENTITY *InterruptQtdsPtr;
2224 UINT8 *DataPtr;
2225 UINT8 *DataCursor;
2226 VOID *DataMap;
2227 UINTN MappedLength;
2228 EHCI_ASYNC_REQUEST *AsyncRequestPtr;
2229 EFI_TPL OldTpl;
2230
2231 QhPtr = NULL;
2232 InterruptQtdsPtr = NULL;
2233 DataPtr = NULL;
2234 DataCursor = NULL;
2235 DataMap = NULL;
2236 AsyncRequestPtr = NULL;
2237 HcDev = USB2_HC_DEV_FROM_THIS (This);
2238
2239 //
2240 // Parameters Checking
2241 //
2242 if (!IsDataInTransfer (EndPointAddress)) {
2243 Status = EFI_INVALID_PARAMETER;
2244 goto exit;
2245 }
2246
2247 if (IsNewTransfer) {
2248 if (0 == DataLength) {
2249 Status = EFI_INVALID_PARAMETER;
2250 goto exit;
2251 }
2252
2253 if (*DataToggle != 1 && *DataToggle != 0) {
2254 Status = EFI_INVALID_PARAMETER;
2255 goto exit;
2256 }
2257
2258 if (PollingInterval > 255 || PollingInterval < 1) {
2259 Status = EFI_INVALID_PARAMETER;
2260 goto exit;
2261 }
2262 }
2263
2264 //
2265 // if has errors that cause host controller halt,
2266 // then return EFI_DEVICE_ERROR directly.
2267 //
2268 if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
2269 ClearEhcAllStatus (HcDev);
2270 Status = EFI_DEVICE_ERROR;
2271 goto exit;
2272 }
2273
2274 Status = ClearEhcAllStatus (HcDev);
2275 if (EFI_ERROR (Status)) {
2276 Status = EFI_DEVICE_ERROR;
2277 goto exit;
2278 }
2279
2280 //
2281 // Delete Async interrupt transfer request
2282 //
2283 if (!IsNewTransfer) {
2284
2285 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
2286
2287 Status = DeleteAsyncRequestTransfer (
2288 HcDev,
2289 DeviceAddress,
2290 EndPointAddress,
2291 DataToggle
2292 );
2293
2294 gBS->RestoreTPL (OldTpl);
2295
2296 goto exit;
2297 }
2298
2299 Status = EhciAllocatePool (
2300 HcDev,
2301 (UINT8 **) &AsyncRequestPtr,
2302 sizeof (EHCI_ASYNC_REQUEST)
2303 );
2304 if (EFI_ERROR (Status)) {
2305 Status = EFI_OUT_OF_RESOURCES;
2306 goto exit;
2307 }
2308
2309 Status = EhciAllocatePool (HcDev, &DataPtr, DataLength);
2310 if (EFI_ERROR (Status)) {
2311 Status = EFI_OUT_OF_RESOURCES;
2312 goto free_request;
2313 }
2314
2315 MappedLength = DataLength;
2316 Status = MapDataBuffer (
2317 HcDev,
2318 EfiUsbDataIn,
2319 DataPtr,
2320 &MappedLength,
2321 &PktId,
2322 &DataCursor,
2323 &DataMap
2324 );
2325 if (EFI_ERROR (Status)) {
2326 Status = EFI_DEVICE_ERROR;
2327 goto free_data;
2328 }
2329
2330 //
2331 // Create and init Interrupt Qh
2332 //
2333 Status = CreateInterruptQh (
2334 HcDev,
2335 DeviceAddress,
2336 EndPointAddress,
2337 DeviceSpeed,
2338 *DataToggle,
2339 MaximumPacketLength,
2340 PollingInterval,
2341 Translator,
2342 &QhPtr
2343 );
2344 if (EFI_ERROR (Status)) {
2345 Status = EFI_OUT_OF_RESOURCES;
2346 goto unmap_data;
2347 }
2348
2349 //
2350 // Create and init Interrupt Qtds
2351 //
2352 Status = CreateBulkOrInterruptQtds (
2353 HcDev,
2354 PktId,
2355 DataCursor,
2356 MappedLength,
2357 Translator,
2358 &InterruptQtdsPtr
2359 );
2360 if (EFI_ERROR (Status)) {
2361 Status = EFI_OUT_OF_RESOURCES;
2362 goto destory_qh;
2363 }
2364
2365 //
2366 // Link Qtds to Qh
2367 //
2368 LinkQtdToQh (QhPtr, InterruptQtdsPtr);
2369
2370 //
2371 // Init AsyncRequest Entry
2372 //
2373 AsyncRequestPtr->Context = Context;
2374 AsyncRequestPtr->CallBackFunc = CallBackFunction;
2375 AsyncRequestPtr->TransferType = ASYNC_INTERRUPT_TRANSFER;
2376 AsyncRequestPtr->QhPtr = QhPtr;
2377 AsyncRequestPtr->Prev = NULL;
2378 AsyncRequestPtr->Next = NULL;
2379
2380 if (NULL == HcDev->AsyncRequestList) {
2381 Status = StartPollingTimer (HcDev);
2382 if (EFI_ERROR (Status)) {
2383 Status = EFI_DEVICE_ERROR;
2384 CleanUpAllAsyncRequestTransfer (HcDev);
2385 goto exit;
2386 }
2387 }
2388
2389 //
2390 // Link Entry to AsyncRequest List
2391 //
2392 LinkToAsyncReqeust (HcDev, AsyncRequestPtr);
2393
2394 ClearEhcAllStatus (HcDev);
2395
2396 Status = DisablePeriodicSchedule (HcDev);
2397 if (EFI_ERROR (Status)) {
2398 Status = EFI_DEVICE_ERROR;
2399 goto exit;
2400 }
2401
2402 Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
2403 if (EFI_ERROR (Status)) {
2404 Status = EFI_TIMEOUT;
2405 goto exit;
2406 }
2407
2408 //
2409 // Link Qh and Qtds to Periodic Schedule List
2410 //
2411 LinkQhToPeriodicList (HcDev, QhPtr);
2412
2413 Status = EnablePeriodicSchedule (HcDev);
2414 if (EFI_ERROR (Status)) {
2415 Status = EFI_DEVICE_ERROR;
2416 goto exit;
2417 }
2418
2419 Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
2420 if (EFI_ERROR (Status)) {
2421 Status = EFI_TIMEOUT;
2422 goto exit;
2423 }
2424
2425 if (IsEhcHalted (HcDev)) {
2426 Status = StartScheduleExecution (HcDev);
2427 if (EFI_ERROR (Status)) {
2428 Status = EFI_DEVICE_ERROR;
2429 goto exit;
2430 }
2431 }
2432
2433 HcDev->PciIo->Flush (HcDev->PciIo);
2434 goto exit;
2435
2436 destory_qh:
2437 DestoryQh (HcDev, QhPtr);
2438 free_data:
2439 EhciFreePool (HcDev, DataPtr, DataLength);
2440 free_request:
2441 EhciFreePool (
2442 HcDev,
2443 (UINT8 *) AsyncRequestPtr,
2444 sizeof (EHCI_ASYNC_REQUEST)
2445 );
2446 unmap_data:
2447 HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
2448 exit:
2449 return Status;
2450 }
2451
2452 EFI_STATUS
2453 EFIAPI
2454 EhciSyncInterruptTransfer (
2455 IN EFI_USB2_HC_PROTOCOL *This,
2456 IN UINT8 DeviceAddress,
2457 IN UINT8 EndPointAddress,
2458 IN UINT8 DeviceSpeed,
2459 IN UINTN MaximumPacketLength,
2460 IN OUT VOID *Data,
2461 IN OUT UINTN *DataLength,
2462 IN OUT UINT8 *DataToggle,
2463 IN UINTN TimeOut,
2464 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
2465 OUT UINT32 *TransferResult
2466 )
2467 /*++
2468
2469 Routine Description:
2470
2471 Submits synchronous interrupt transfer to an interrupt endpoint
2472 of a USB device.
2473
2474 Arguments:
2475
2476 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
2477 DeviceAddress - Represents the address of the target device on the USB,
2478 which is assigned during USB enumeration.
2479 EndPointAddress - The combination of an endpoint number and an endpoint
2480 direction of the target USB device. Each endpoint
2481 address supports data transfer in one direction
2482 except the control endpoint (whose default
2483 endpoint address is 0). It is the caller's responsibility
2484 to make sure that the EndPointAddress represents
2485 an interrupt endpoint.
2486 DeviceSpeed - Indicates device speed.
2487 MaximumPacketLength - Indicates the maximum packet size the target endpoint
2488 is capable of sending or receiving.
2489 Data - A pointer to the buffer of data that will be transmitted
2490 to USB device or received from USB device.
2491 DataLength - On input, the size, in bytes, of the data buffer specified
2492 by Data. On output, the number of bytes transferred.
2493 DataToggle - A pointer to the data toggle value. On input, it indicates
2494 the initial data toggle value the synchronous interrupt
2495 transfer should adopt;
2496 on output, it is updated to indicate the data toggle value
2497 of the subsequent synchronous interrupt transfer.
2498 TimeOut - Indicates the maximum time, in microseconds, which the
2499 transfer is allowed to complete.
2500 Translator - A pointr to the transaction translator data.
2501 TransferResult - A pointer to the detailed result information from
2502 the synchronous interrupt transfer.
2503
2504 Returns:
2505
2506 EFI_SUCCESS
2507 The synchronous interrupt transfer was completed successfully.
2508 EFI_OUT_OF_RESOURCES
2509 The synchronous interrupt transfer could not be submitted due
2510 to lack of resource.
2511 EFI_INVALID_PARAMETER
2512 Some parameters are invalid.
2513 EFI_TIMEOUT
2514 The synchronous interrupt transfer failed due to timeout.
2515 EFI_DEVICE_ERROR
2516 The synchronous interrupt transfer failed due to host controller
2517 or device error. Caller should check TranferResult for detailed
2518 error information.
2519
2520 --*/
2521 {
2522 EFI_STATUS Status;
2523 USB2_HC_DEV *HcDev;
2524 UINT8 PktId;
2525 EHCI_QH_ENTITY *QhPtr;
2526 EHCI_QTD_ENTITY *InterruptQtdsPtr;
2527 UINT8 *DataCursor;
2528 VOID *DataMap;
2529
2530 QhPtr = NULL;
2531 InterruptQtdsPtr = NULL;
2532 DataCursor = NULL;
2533 DataMap = NULL;
2534 HcDev = USB2_HC_DEV_FROM_THIS (This);
2535
2536 //
2537 // Parameters Checking
2538 //
2539 if (DataLength == NULL ||
2540 Data == NULL ||
2541 TransferResult == NULL
2542 ) {
2543 Status = EFI_INVALID_PARAMETER;
2544 goto exit;
2545 }
2546
2547 if (!IsDataInTransfer (EndPointAddress)) {
2548 Status = EFI_INVALID_PARAMETER;
2549 goto exit;
2550 }
2551
2552 if (0 == *DataLength) {
2553 Status = EFI_INVALID_PARAMETER;
2554 goto exit;
2555 }
2556
2557 if (*DataToggle != 1 && *DataToggle != 0) {
2558 Status = EFI_INVALID_PARAMETER;
2559 goto exit;
2560 }
2561
2562 if (EFI_USB_SPEED_LOW == DeviceSpeed && 8 != MaximumPacketLength) {
2563 Status = EFI_INVALID_PARAMETER;
2564 goto exit;
2565 }
2566
2567 if (EFI_USB_SPEED_FULL == DeviceSpeed && MaximumPacketLength > 64) {
2568 Status = EFI_INVALID_PARAMETER;
2569 goto exit;
2570 }
2571
2572 if (EFI_USB_SPEED_HIGH == DeviceSpeed && MaximumPacketLength > 3072) {
2573 Status = EFI_INVALID_PARAMETER;
2574 goto exit;
2575 }
2576
2577 //
2578 // if has errors that cause host controller halt,
2579 // then return EFI_DEVICE_ERROR directly.
2580 //
2581 if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
2582 ClearEhcAllStatus (HcDev);
2583 *TransferResult = EFI_USB_ERR_SYSTEM;
2584 Status = EFI_DEVICE_ERROR;
2585 goto exit;
2586 }
2587
2588 Status = ClearEhcAllStatus (HcDev);
2589 if (EFI_ERROR (Status)) {
2590 Status = EFI_DEVICE_ERROR;
2591 goto exit;
2592 }
2593
2594 Status = MapDataBuffer (
2595 HcDev,
2596 EfiUsbDataIn,
2597 Data,
2598 DataLength,
2599 &PktId,
2600 &DataCursor,
2601 &DataMap
2602 );
2603 if (EFI_ERROR (Status)) {
2604 *TransferResult = EFI_USB_ERR_SYSTEM;
2605 Status = EFI_DEVICE_ERROR;
2606 goto exit;
2607 }
2608
2609 //
2610 // Create and init Interrupt Qh
2611 //
2612 Status = CreateInterruptQh (
2613 HcDev,
2614 DeviceAddress,
2615 EndPointAddress,
2616 DeviceSpeed,
2617 *DataToggle,
2618 MaximumPacketLength,
2619 0,
2620 Translator,
2621 &QhPtr
2622 );
2623 if (EFI_ERROR (Status)) {
2624 Status = EFI_OUT_OF_RESOURCES;
2625 goto unmap_data;
2626 }
2627
2628 //
2629 // Create and init Interrupt Qtds
2630 //
2631 Status = CreateBulkOrInterruptQtds (
2632 HcDev,
2633 PktId,
2634 DataCursor,
2635 *DataLength,
2636 Translator,
2637 &InterruptQtdsPtr
2638 );
2639 if (EFI_ERROR (Status)) {
2640 *TransferResult = EFI_USB_ERR_SYSTEM;
2641 Status = EFI_OUT_OF_RESOURCES;
2642 goto destory_qh;
2643 }
2644
2645 //
2646 // Link Qtds to Qh
2647 //
2648 LinkQtdToQh (QhPtr, InterruptQtdsPtr);
2649
2650 ClearEhcAllStatus (HcDev);
2651
2652 Status = DisablePeriodicSchedule (HcDev);
2653 if (EFI_ERROR (Status)) {
2654 Status = EFI_DEVICE_ERROR;
2655 goto exit;
2656 }
2657
2658 Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
2659 if (EFI_ERROR (Status)) {
2660 Status = EFI_TIMEOUT;
2661 goto exit;
2662 }
2663
2664 //
2665 // Link Qh and Qtds to Periodic Schedule List
2666 //
2667 LinkQhToPeriodicList (HcDev, QhPtr);
2668
2669 Status = EnablePeriodicSchedule (HcDev);
2670 if (EFI_ERROR (Status)) {
2671 Status = EFI_DEVICE_ERROR;
2672 goto exit;
2673 }
2674
2675 Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
2676 if (EFI_ERROR (Status)) {
2677 Status = EFI_TIMEOUT;
2678 goto exit;
2679 }
2680
2681 if (IsEhcHalted (HcDev)) {
2682 Status = StartScheduleExecution (HcDev);
2683 if (EFI_ERROR (Status)) {
2684 Status = EFI_DEVICE_ERROR;
2685 goto exit;
2686 }
2687 }
2688
2689 //
2690 // Poll QH-TDs execution and get result.
2691 // detail status is returned
2692 //
2693 Status = ExecuteTransfer (
2694 HcDev,
2695 FALSE,
2696 QhPtr,
2697 DataLength,
2698 DataToggle,
2699 TimeOut,
2700 TransferResult
2701 );
2702 if (EFI_ERROR (Status)) {
2703 goto destory_qtds;
2704 }
2705
2706 //
2707 // if has errors that cause host controller halt,
2708 // then return EFI_DEVICE_ERROR directly.
2709 //
2710 if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
2711 *TransferResult |= EFI_USB_ERR_SYSTEM;
2712 }
2713
2714 ClearEhcAllStatus (HcDev);
2715
2716 destory_qtds:
2717 UnlinkQhFromPeriodicList (HcDev, QhPtr, 0);
2718 DestoryQtds (HcDev, InterruptQtdsPtr);
2719 destory_qh:
2720 DestoryQh (HcDev, QhPtr);
2721 unmap_data:
2722 HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
2723 exit:
2724 HcDev->PciIo->Flush (HcDev->PciIo);
2725 return Status;
2726 }
2727
2728 EFI_STATUS
2729 EFIAPI
2730 EhciIsochronousTransfer (
2731 IN EFI_USB2_HC_PROTOCOL *This,
2732 IN UINT8 DeviceAddress,
2733 IN UINT8 EndPointAddress,
2734 IN UINT8 DeviceSpeed,
2735 IN UINTN MaximumPacketLength,
2736 IN UINT8 DataBuffersNumber,
2737 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
2738 IN UINTN DataLength,
2739 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
2740 OUT UINT32 *TransferResult
2741 )
2742 /*++
2743
2744 Routine Description:
2745
2746 Submits isochronous transfer to a target USB device.
2747
2748 Arguments:
2749
2750 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
2751 DeviceAddress - Represents the address of the target device on the USB,
2752 which is assigned during USB enumeration.
2753 EndPointAddress - End point address
2754 DeviceSpeed - Indicates device speed.
2755 MaximumPacketLength - Indicates the maximum packet size that the
2756 default control transfer endpoint is capable of
2757 sending or receiving.
2758 DataBuffersNumber - Number of data buffers prepared for the transfer.
2759 Data - Array of pointers to the buffers of data that will be
2760 transmitted to USB device or received from USB device.
2761 DataLength - Indicates the size, in bytes, of the data buffer
2762 specified by Data.
2763 Translator - A pointr to the transaction translator data.
2764 TransferResult - A pointer to the detailed result information generated
2765 by this control transfer.
2766
2767 Returns:
2768
2769 EFI_UNSUPPORTED
2770
2771 --*/
2772 {
2773 return EFI_UNSUPPORTED;
2774 }
2775
2776 EFI_STATUS
2777 EFIAPI
2778 EhciAsyncIsochronousTransfer (
2779 IN EFI_USB2_HC_PROTOCOL *This,
2780 IN UINT8 DeviceAddress,
2781 IN UINT8 EndPointAddress,
2782 IN UINT8 DeviceSpeed,
2783 IN UINTN MaximumPacketLength,
2784 IN UINT8 DataBuffersNumber,
2785 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
2786 IN UINTN DataLength,
2787 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
2788 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
2789 IN VOID *Context
2790 )
2791 /*++
2792
2793 Routine Description:
2794
2795 Submits Async isochronous transfer to a target USB device.
2796
2797 Arguments:
2798
2799 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
2800 DeviceAddress - Represents the address of the target device on the USB,
2801 which is assigned during USB enumeration.
2802 EndPointAddress - End point address
2803 DeviceSpeed - Indicates device speed.
2804 MaximumPacketLength - Indicates the maximum packet size that the
2805 default control transfer endpoint is capable of
2806 sending or receiving.
2807 DataBuffersNumber - Number of data buffers prepared for the transfer.
2808 Data - Array of pointers to the buffers of data that will be transmitted
2809 to USB device or received from USB device.
2810 Translator - A pointr to the transaction translator data.
2811 IsochronousCallBack - When the transfer complete, the call back function will be called
2812 Context - Pass to the call back function as parameter
2813
2814 Returns:
2815
2816 EFI_UNSUPPORTED
2817
2818 --*/
2819 {
2820 return EFI_UNSUPPORTED;
2821 }