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