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