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