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