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