]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c
Make EdkModulePkg pass Intel IPF compiler with /W4 /WX switches, solving warning...
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / Uhci / Dxe / uhci.c
CommitLineData
878ddf1f 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 Uhci.c\r
15 \r
16Abstract: \r
17 \r
18\r
19Revision History\r
20--*/\r
21\r
22#include "uhci.h"\r
23\r
878ddf1f 24//\r
25// UHCI Driver Global Variables\r
26//\r
27EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding = {\r
28 UHCIDriverBindingSupported,\r
29 UHCIDriverBindingStart,\r
30 UHCIDriverBindingStop,\r
61fb1657 31 0xa,\r
878ddf1f 32 NULL,\r
33 NULL\r
34};\r
35\r
36EFI_STATUS\r
37EFIAPI\r
38UHCIDriverBindingSupported (\r
39 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
40 IN EFI_HANDLE Controller,\r
41 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
42 )\r
43/*++\r
44\r
45 Routine Description:\r
46 Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
47 that has UsbHcProtocol installed will be supported.\r
48\r
49 Arguments:\r
50 This - Protocol instance pointer.\r
562d2849 51 Controller - Handle of device to test\r
878ddf1f 52 RemainingDevicePath - Not used\r
53\r
54 Returns:\r
55 EFI_SUCCESS - This driver supports this device.\r
56 EFI_UNSUPPORTED - This driver does not support this device.\r
57\r
58--*/\r
59{\r
60 EFI_STATUS OpenStatus;\r
61 EFI_STATUS Status;\r
62 EFI_PCI_IO_PROTOCOL *PciIo;\r
63 USB_CLASSC UsbClassCReg;\r
64\r
65 //\r
66 // Test whether there is PCI IO Protocol attached on the controller handle.\r
67 //\r
68 OpenStatus = gBS->OpenProtocol (\r
69 Controller,\r
70 &gEfiPciIoProtocolGuid,\r
71 (VOID **) &PciIo,\r
72 This->DriverBindingHandle,\r
73 Controller,\r
74 EFI_OPEN_PROTOCOL_BY_DRIVER\r
75 );\r
76 if (EFI_ERROR (OpenStatus)) {\r
77 return OpenStatus;\r
78 }\r
79\r
80 Status = PciIo->Pci.Read (\r
81 PciIo,\r
82 EfiPciIoWidthUint8,\r
83 CLASSC,\r
84 sizeof (USB_CLASSC) / sizeof (UINT8),\r
85 &UsbClassCReg\r
86 );\r
87 if (EFI_ERROR (Status)) {\r
88 gBS->CloseProtocol (\r
89 Controller,\r
90 &gEfiPciIoProtocolGuid,\r
91 This->DriverBindingHandle,\r
92 Controller\r
93 );\r
94 return EFI_UNSUPPORTED;\r
95 }\r
96 //\r
97 // Test whether the controller belongs to UHCI type\r
98 //\r
99 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
100 (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
101 (UsbClassCReg.PI != PCI_CLASSC_PI_UHCI)) {\r
102\r
103 gBS->CloseProtocol (\r
562d2849 104 Controller,\r
105 &gEfiPciIoProtocolGuid,\r
106 This->DriverBindingHandle,\r
107 Controller\r
108 );\r
878ddf1f 109\r
110 return EFI_UNSUPPORTED;\r
111 }\r
112 gBS->CloseProtocol (\r
562d2849 113 Controller,\r
114 &gEfiPciIoProtocolGuid,\r
115 This->DriverBindingHandle,\r
116 Controller\r
117 );\r
878ddf1f 118 return EFI_SUCCESS;\r
119\r
120}\r
121\r
122EFI_STATUS\r
123EFIAPI\r
124UHCIDriverBindingStart (\r
125 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
126 IN EFI_HANDLE Controller,\r
127 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
128 )\r
129/*++\r
130\r
131 Routine Description:\r
132 Starting the Usb UHCI Driver\r
133\r
134 Arguments:\r
135 This - Protocol instance pointer.\r
136 Controller - Handle of device to test\r
137 RemainingDevicePath - Not used\r
138\r
139 Returns:\r
140 EFI_SUCCESS - This driver supports this device.\r
141 EFI_UNSUPPORTED - This driver does not support this device.\r
142 EFI_DEVICE_ERROR - This driver cannot be started due to device\r
143 Error\r
144 EFI_OUT_OF_RESOURCES\r
145\r
146--*/\r
147{ \r
148 EFI_STATUS Status; \r
149 UINTN FlBaseAddrReg; \r
150 EFI_PCI_IO_PROTOCOL *PciIo; \r
151 USB_HC_DEV *HcDev;\r
4d1fe68e 152 UINT64 Supports;\r
878ddf1f 153 \r
154 HcDev = NULL;\r
155\r
156 Status = gBS->OpenProtocol (\r
157 Controller,\r
158 &gEfiPciIoProtocolGuid,\r
159 (VOID **) &PciIo,\r
160 This->DriverBindingHandle,\r
161 Controller,\r
162 EFI_OPEN_PROTOCOL_BY_DRIVER\r
163 );\r
164 if (EFI_ERROR (Status)) {\r
165 return Status;\r
166 }\r
562d2849 167\r
878ddf1f 168 //\r
169 // Turn off USB emulation\r
170 //\r
171 TurnOffUSBEmulation (PciIo);\r
172\r
173 //\r
174 // Enable the USB Host Controller\r
175 //\r
176 Status = PciIo->Attributes (\r
177 PciIo,\r
4d1fe68e 178 EfiPciIoAttributeOperationSupported,\r
179 0,\r
180 &Supports\r
878ddf1f 181 );\r
4d1fe68e 182 if (!EFI_ERROR (Status)) {\r
183 Supports &= EFI_PCI_DEVICE_ENABLE;\r
184 Status = PciIo->Attributes (\r
185 PciIo,\r
186 EfiPciIoAttributeOperationEnable,\r
187 Supports,\r
188 NULL\r
189 );\r
190 }\r
878ddf1f 191 if (EFI_ERROR (Status)) {\r
192 gBS->CloseProtocol (\r
562d2849 193 Controller,\r
194 &gEfiPciIoProtocolGuid,\r
195 This->DriverBindingHandle,\r
196 Controller\r
197 );\r
878ddf1f 198 return EFI_UNSUPPORTED;\r
199 }\r
200\r
201 //\r
202 // allocate memory for UHC private data structure\r
203 //\r
204 HcDev = AllocateZeroPool (sizeof (USB_HC_DEV));\r
205 if (HcDev == NULL) {\r
206 gBS->CloseProtocol (\r
562d2849 207 Controller,\r
208 &gEfiPciIoProtocolGuid,\r
209 This->DriverBindingHandle,\r
210 Controller\r
211 );\r
878ddf1f 212 return EFI_OUT_OF_RESOURCES;\r
213 }\r
562d2849 214\r
878ddf1f 215 //\r
216 // init EFI_USB_HC_PROTOCOL protocol interface and install the protocol\r
217 //\r
218 HcDev->UsbHc.Reset = UHCIReset;\r
219 HcDev->UsbHc.GetState = UHCIGetState;\r
220 HcDev->UsbHc.SetState = UHCISetState;\r
221 HcDev->UsbHc.ControlTransfer = UHCIControlTransfer;\r
222 HcDev->UsbHc.BulkTransfer = UHCIBulkTransfer;\r
223 HcDev->UsbHc.AsyncInterruptTransfer = UHCIAsyncInterruptTransfer;\r
224 HcDev->UsbHc.SyncInterruptTransfer = UHCISyncInterruptTransfer;\r
225 HcDev->UsbHc.IsochronousTransfer = UHCIIsochronousTransfer;\r
226 HcDev->UsbHc.AsyncIsochronousTransfer = UHCIAsyncIsochronousTransfer;\r
227 HcDev->UsbHc.GetRootHubPortNumber = UHCIGetRootHubPortNumber;\r
228 HcDev->UsbHc.GetRootHubPortStatus = UHCIGetRootHubPortStatus;\r
229 HcDev->UsbHc.SetRootHubPortFeature = UHCISetRootHubPortFeature;\r
230 HcDev->UsbHc.ClearRootHubPortFeature = UHCIClearRootHubPortFeature;\r
231\r
232 HcDev->UsbHc.MajorRevision = 0x1;\r
233 HcDev->UsbHc.MinorRevision = 0x1;\r
234\r
562d2849 235 //\r
236 //\r
237 // init EFI_USB2_HC_PROTOCOL protocol interface and install the protocol\r
238 //\r
239 HcDev->Usb2Hc.GetCapability = UHCI2GetCapability;\r
240 HcDev->Usb2Hc.Reset = UHCI2Reset;\r
241 HcDev->Usb2Hc.GetState = UHCI2GetState;\r
242 HcDev->Usb2Hc.SetState = UHCI2SetState;\r
243 HcDev->Usb2Hc.ControlTransfer = UHCI2ControlTransfer;\r
244 HcDev->Usb2Hc.BulkTransfer = UHCI2BulkTransfer;\r
245 HcDev->Usb2Hc.AsyncInterruptTransfer = UHCI2AsyncInterruptTransfer;\r
246 HcDev->Usb2Hc.SyncInterruptTransfer = UHCI2SyncInterruptTransfer;\r
247 HcDev->Usb2Hc.IsochronousTransfer = UHCI2IsochronousTransfer;\r
248 HcDev->Usb2Hc.AsyncIsochronousTransfer = UHCI2AsyncIsochronousTransfer;\r
249 HcDev->Usb2Hc.GetRootHubPortStatus = UHCI2GetRootHubPortStatus;\r
250 HcDev->Usb2Hc.SetRootHubPortFeature = UHCI2SetRootHubPortFeature;\r
251 HcDev->Usb2Hc.ClearRootHubPortFeature = UHCI2ClearRootHubPortFeature;\r
252 \r
253 HcDev->Usb2Hc.MajorRevision = 0x1;\r
254 HcDev->Usb2Hc.MinorRevision = 0x1;\r
255 \r
878ddf1f 256 //\r
257 // Init UHCI private data structures\r
258 //\r
259 HcDev->Signature = USB_HC_DEV_SIGNATURE;\r
260 HcDev->PciIo = PciIo;\r
261\r
262 FlBaseAddrReg = USBFLBASEADD;\r
263\r
264 //\r
265 // Allocate and Init Host Controller's Frame List Entry\r
266 //\r
267 Status = CreateFrameList (HcDev, (UINT32) FlBaseAddrReg);\r
268 if (EFI_ERROR (Status)) {\r
269\r
270 if (HcDev != NULL) {\r
271 gBS->FreePool (HcDev);\r
272 }\r
273\r
274 gBS->CloseProtocol (\r
562d2849 275 Controller,\r
276 &gEfiPciIoProtocolGuid,\r
277 This->DriverBindingHandle,\r
278 Controller\r
279 );\r
878ddf1f 280 return EFI_OUT_OF_RESOURCES;\r
281 }\r
562d2849 282\r
878ddf1f 283 //\r
284 // Init interrupt list head in the HcDev structure.\r
285 //\r
286 InitializeListHead (&(HcDev->InterruptListHead));\r
287\r
288 //\r
289 // Create timer for interrupt transfer result polling\r
290 //\r
291 Status = gBS->CreateEvent (\r
292 EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,\r
293 EFI_TPL_NOTIFY,\r
294 MonitorInterruptTrans,\r
295 HcDev,\r
296 &HcDev->InterruptTransTimer\r
297 );\r
298 if (EFI_ERROR (Status)) {\r
299\r
300 FreeFrameListEntry (HcDev);\r
301\r
302 if (HcDev != NULL) {\r
303 gBS->FreePool (HcDev);\r
304 }\r
305\r
306 gBS->CloseProtocol (\r
562d2849 307 Controller,\r
308 &gEfiPciIoProtocolGuid,\r
309 This->DriverBindingHandle,\r
310 Controller\r
311 );\r
878ddf1f 312 return EFI_UNSUPPORTED;\r
313 }\r
314\r
315 //\r
316 // Here set interrupt transfer polling timer in 50ms unit.\r
317 //\r
318 Status = gBS->SetTimer (\r
319 HcDev->InterruptTransTimer,\r
320 TimerPeriodic,\r
321 INTERRUPT_POLLING_TIME\r
322 );\r
323 if (EFI_ERROR (Status)) {\r
324 gBS->CloseEvent (HcDev->InterruptTransTimer);\r
325\r
326 FreeFrameListEntry (HcDev);\r
327\r
328 if (HcDev != NULL) {\r
329 gBS->FreePool (HcDev);\r
330 }\r
331\r
332 gBS->CloseProtocol (\r
562d2849 333 Controller,\r
334 &gEfiPciIoProtocolGuid,\r
335 This->DriverBindingHandle,\r
336 Controller\r
337 );\r
878ddf1f 338 return EFI_UNSUPPORTED;\r
339 }\r
340 \r
341 //\r
342 // QH,TD structures must in common buffer that will be\r
343 // accessed by both cpu and usb bus master at the same time.\r
344 // so, there must has memory management for QH,TD structures.\r
345 //\r
346 Status = InitializeMemoryManagement (HcDev);\r
347 if (EFI_ERROR (Status)) {\r
348 \r
349 gBS->CloseEvent (HcDev->InterruptTransTimer);\r
350 \r
351 FreeFrameListEntry (HcDev);\r
352\r
353 if (HcDev != NULL) {\r
354 gBS->FreePool (HcDev);\r
355 }\r
356\r
357 gBS->CloseProtocol (\r
358 Controller, \r
359 &gEfiPciIoProtocolGuid, \r
360 This->DriverBindingHandle, \r
361 Controller\r
362 );\r
363 return Status;\r
364 }\r
562d2849 365\r
878ddf1f 366 //\r
367 // Install Host Controller Protocol\r
368 //\r
369 Status = gBS->InstallProtocolInterface (\r
370 &Controller,\r
371 &gEfiUsbHcProtocolGuid,\r
372 EFI_NATIVE_INTERFACE,\r
373 &HcDev->UsbHc\r
374 );\r
375 if (EFI_ERROR (Status)) {\r
376 gBS->CloseEvent (HcDev->InterruptTransTimer);\r
377 FreeFrameListEntry (HcDev);\r
378 DelMemoryManagement (HcDev);\r
379\r
380 if (HcDev != NULL) {\r
381 gBS->FreePool (HcDev);\r
382 }\r
383\r
384 gBS->CloseProtocol (\r
562d2849 385 Controller,\r
386 &gEfiPciIoProtocolGuid,\r
387 This->DriverBindingHandle,\r
388 Controller\r
389 );\r
390 return Status;\r
391 }\r
392\r
393 //\r
394 // Install USB2.0 Host Controller Protocol\r
395 //\r
396 Status = gBS->InstallProtocolInterface (\r
397 &Controller,\r
398 &gEfiUsb2HcProtocolGuid,\r
399 EFI_NATIVE_INTERFACE,\r
400 &HcDev->Usb2Hc\r
401 );\r
402 if (EFI_ERROR (Status)) {\r
403 gBS->CloseEvent (HcDev->InterruptTransTimer);\r
404 FreeFrameListEntry (HcDev);\r
405 DelMemoryManagement (HcDev);\r
406\r
407 if (HcDev != NULL) {\r
408 gBS->FreePool (HcDev);\r
409 }\r
410\r
411 gBS->CloseProtocol (\r
412 Controller,\r
413 &gEfiPciIoProtocolGuid,\r
414 This->DriverBindingHandle,\r
415 Controller\r
416 );\r
417\r
878ddf1f 418 return Status;\r
419 }\r
420 \r
421 //\r
422 // component name protocol.\r
423 //\r
562d2849 424\r
878ddf1f 425 HcDev->ControllerNameTable = NULL;\r
426 AddUnicodeString (\r
427 "eng",\r
428 gUhciComponentName.SupportedLanguages,\r
429 &HcDev->ControllerNameTable,\r
430 (CHAR16 *) L"Usb Universal Host Controller"\r
431 );\r
432\r
433 return EFI_SUCCESS;\r
434}\r
435\r
1cc8ee78 436STATIC\r
878ddf1f 437EFI_STATUS\r
438UnInstallUHCInterface (\r
439 IN EFI_HANDLE Controller,\r
440 IN EFI_USB_HC_PROTOCOL *This\r
441 )\r
442/*++\r
443 Routine Description:\r
444 UnInstall UHCInterface\r
445 Arguments:\r
446 Controller - Controller handle\r
447 This - Protocol instance pointer.\r
448 Returns:\r
449 EFI_SUCCESS\r
450 others\r
451--*/\r
452{\r
453 USB_HC_DEV *HcDev;\r
4d1fe68e 454 EFI_STATUS Status;\r
455 UINT64 Supports;\r
878ddf1f 456\r
457 HcDev = USB_HC_DEV_FROM_THIS (This);\r
458\r
459 gBS->UninstallProtocolInterface (\r
562d2849 460 Controller,\r
461 &gEfiUsbHcProtocolGuid,\r
462 &HcDev->UsbHc\r
463 );\r
464 \r
465 gBS->UninstallProtocolInterface (\r
466 Controller,\r
467 &gEfiUsb2HcProtocolGuid,\r
468 &HcDev->Usb2Hc\r
469 );\r
470 // \r
878ddf1f 471 // first stop USB Host Controller\r
472 //\r
473 This->SetState (This, EfiUsbHcStateHalt);\r
474\r
475 //\r
476 // Delete interrupt transfer polling timer\r
477 //\r
478 gBS->CloseEvent (HcDev->InterruptTransTimer);\r
479\r
480 //\r
481 // Delete all the asynchronous interrupt transfers in the interrupt list\r
482 // and free associated memory\r
483 //\r
484 ReleaseInterruptList (HcDev, &(HcDev->InterruptListHead));\r
485\r
486 //\r
487 // free Frame List Entry.\r
488 //\r
489 FreeFrameListEntry (HcDev);\r
490\r
491 //\r
492 // Free common buffer allocated for QH,TD structures\r
493 //\r
494 DelMemoryManagement (HcDev);\r
495\r
496 if (HcDev->ControllerNameTable) {\r
497 FreeUnicodeStringTable (HcDev->ControllerNameTable);\r
498 }\r
499 //\r
500 // Disable the USB Host Controller\r
501 //\r
4d1fe68e 502 Status = HcDev->PciIo->Attributes (\r
503 HcDev->PciIo,\r
504 EfiPciIoAttributeOperationSupported,\r
505 0,\r
506 &Supports\r
507 );\r
508 if (!EFI_ERROR (Status)) {\r
509 Supports &= EFI_PCI_DEVICE_ENABLE;\r
510 Status = HcDev->PciIo->Attributes (\r
511 HcDev->PciIo,\r
512 EfiPciIoAttributeOperationDisable,\r
513 Supports,\r
514 NULL\r
515 );\r
516 }\r
878ddf1f 517\r
518 gBS->FreePool (HcDev);\r
519\r
520 return EFI_SUCCESS;\r
521}\r
522\r
523\r
524EFI_STATUS\r
525EFIAPI\r
526UHCIDriverBindingStop (\r
527 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
528 IN EFI_HANDLE Controller,\r
529 IN UINTN NumberOfChildren,\r
530 IN EFI_HANDLE *ChildHandleBuffer\r
531 )\r
532/*++\r
533\r
534 Routine Description:\r
535 Stop this driver on ControllerHandle. Support stoping any child handles\r
536 created by this driver.\r
537\r
538 Arguments:\r
539 This - Protocol instance pointer.\r
540 Controller - Handle of device to stop driver on\r
541 NumberOfChildren - Number of Children in the ChildHandleBuffer\r
542 ChildHandleBuffer - List of handles for the children we need to stop.\r
543\r
544 Returns:\r
545 EFI_SUCCESS\r
546 others\r
547\r
548--*/\r
549{\r
550 EFI_USB_HC_PROTOCOL *UsbHc;\r
562d2849 551 EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
878ddf1f 552 EFI_STATUS OpenStatus;\r
553\r
554 OpenStatus = gBS->OpenProtocol (\r
555 Controller,\r
556 &gEfiUsbHcProtocolGuid,\r
562d2849 557 (VOID **)&UsbHc,\r
558 This->DriverBindingHandle,\r
559 Controller,\r
560 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
561 );\r
562\r
563 //\r
564 // Test whether the Controller handler passed in is a valid\r
565 // Usb controller handle that should be supported, if not,\r
566 // return the error status directly\r
567 //\r
568 if (EFI_ERROR (OpenStatus)) {\r
569 return OpenStatus;\r
570 }\r
571\r
572 OpenStatus = gBS->OpenProtocol (\r
573 Controller,\r
574 &gEfiUsb2HcProtocolGuid,\r
575 (VOID **) &Usb2Hc,\r
878ddf1f 576 This->DriverBindingHandle,\r
577 Controller,\r
578 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
579 );\r
580\r
581 //\r
582 // Test whether the Controller handler passed in is a valid\r
583 // Usb controller handle that should be supported, if not,\r
584 // return the error status directly\r
585 //\r
586 if (EFI_ERROR (OpenStatus)) {\r
587 return OpenStatus;\r
588 }\r
589 //\r
590 // free all the controller related memory and uninstall UHCI Protocol.\r
591 //\r
592 UnInstallUHCInterface (Controller, UsbHc);\r
593\r
594 gBS->CloseProtocol (\r
562d2849 595 Controller,\r
596 &gEfiPciIoProtocolGuid,\r
597 This->DriverBindingHandle,\r
598 Controller\r
599 );\r
878ddf1f 600\r
601 return EFI_SUCCESS;\r
602\r
603}\r
604\r
605\r
606EFI_STATUS\r
607EFIAPI\r
608UHCIReset (\r
609 IN EFI_USB_HC_PROTOCOL *This,\r
610 IN UINT16 Attributes\r
611 )\r
612/*++\r
613 \r
614 Routine Description:\r
615 Provides software reset for the USB host controller.\r
616 \r
617 Arguments:\r
618 \r
619 This A pointer to the EFI_USB_HC_PROTOCOL instance. \r
620 \r
621 Attributes A bit mask of the reset operation to perform. \r
622 See below for a list of the supported bit mask values.\r
623 \r
624 #define EFI_USB_HC_RESET_GLOBAL 0x0001\r
625 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002\r
626\r
627 EFI_USB_HC_RESET_GLOBAL \r
628 If this bit is set, a global reset signal will be sent to the USB bus.\r
629 This resets all of the USB bus logic, including the USB host \r
630 controller hardware and all the devices attached on the USB bus.\r
631 EFI_USB_HC_RESET_HOST_CONTROLLER \r
632 If this bit is set, the USB host controller hardware will be reset. \r
633 No reset signal will be sent to the USB bus.\r
634 \r
635 Returns:\r
636 EFI_SUCCESS \r
637 The reset operation succeeded.\r
638 EFI_INVALID_PARAMETER \r
639 Attributes is not valid.\r
640 EFI_DEVICE_ERROR \r
641 An error was encountered while attempting to perform \r
642 the reset operation.\r
643--*/\r
644{\r
645 BOOLEAN Match;\r
646 USB_HC_DEV *HcDev;\r
647 UINT32 CommandRegAddr;\r
648 UINT32 FlBaseAddrReg;\r
649 UINT16 Command;\r
650 EFI_STATUS Status;\r
651\r
652 Match = FALSE;\r
653 HcDev = USB_HC_DEV_FROM_THIS (This);\r
654\r
655 CommandRegAddr = (UINT32) (USBCMD);\r
656 FlBaseAddrReg = (UINT32) (USBFLBASEADD);\r
657\r
658 if ((Attributes & EFI_USB_HC_RESET_GLOBAL) != 0) {\r
659 Match = TRUE;\r
660 //\r
661 // set the Global Reset bit in the command register\r
662 //\r
663 Status = ReadUHCCommandReg (\r
562d2849 664 HcDev->PciIo,\r
665 CommandRegAddr,\r
666 &Command\r
667 );\r
878ddf1f 668 if (EFI_ERROR (Status)) {\r
669 return EFI_DEVICE_ERROR;\r
670 }\r
671\r
672 Command |= USBCMD_GRESET;\r
673 Status = WriteUHCCommandReg (\r
562d2849 674 HcDev->PciIo,\r
675 CommandRegAddr,\r
676 Command\r
677 );\r
878ddf1f 678 if (EFI_ERROR (Status)) {\r
679 return EFI_DEVICE_ERROR;\r
680 }\r
681\r
682 //\r
683 // Wait 50ms for root port to let reset complete\r
684 // See UHCI spec page122 Reset signaling\r
685 //\r
686 gBS->Stall (ROOT_PORT_REST_TIME);\r
687\r
688 //\r
689 // Clear the Global Reset bit to zero.\r
690 //\r
691 Command &= ~USBCMD_GRESET;\r
692 Status = WriteUHCCommandReg (\r
562d2849 693 HcDev->PciIo,\r
694 CommandRegAddr,\r
695 Command\r
696 );\r
878ddf1f 697 if (EFI_ERROR (Status)) {\r
698 return EFI_DEVICE_ERROR;\r
699 }\r
700 //\r
701 // UHCI spec page120 reset recovery time\r
702 //\r
703 gBS->Stall (PORT_RESET_RECOVERY_TIME);\r
704 }\r
705\r
706 if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) {\r
707 Match = TRUE;\r
708 //\r
709 // set Host Controller Reset bit to 1\r
710 //\r
711 Status = ReadUHCCommandReg (\r
562d2849 712 HcDev->PciIo,\r
713 CommandRegAddr,\r
714 &Command\r
715 );\r
878ddf1f 716 if (EFI_ERROR (Status)) {\r
717 return EFI_DEVICE_ERROR;\r
718 }\r
719\r
720 Command |= USBCMD_HCRESET;\r
721 Status = WriteUHCCommandReg (\r
562d2849 722 HcDev->PciIo,\r
723 CommandRegAddr,\r
724 Command\r
725 );\r
878ddf1f 726 if (EFI_ERROR (Status)) {\r
727 return EFI_DEVICE_ERROR;\r
728 }\r
729 //\r
730 // this bit will be reset by Host Controller when reset is completed.\r
731 // wait 10ms to let reset complete\r
732 //\r
733 gBS->Stall (PORT_RESET_RECOVERY_TIME);\r
734 }\r
735\r
736 if (!Match) {\r
737 return EFI_INVALID_PARAMETER;\r
738 }\r
739 \r
740 //\r
741 // Delete all old transactions on the USB bus\r
742 //\r
743 CleanUsbTransactions (HcDev);\r
744\r
745 //\r
746 // Initialize Universal Host Controller's Frame List Data Structure\r
747 //\r
748 InitFrameList (HcDev);\r
749\r
750 //\r
751 // Reset may cause Frame List Base Address Register reset to zero,\r
752 // so set the original value back again.\r
753 //\r
754 SetFrameListBaseAddress (\r
755 HcDev->PciIo,\r
756 FlBaseAddrReg,\r
757 (UINT32) ((UINTN) HcDev->FrameListEntry)\r
758 );\r
759\r
760 return EFI_SUCCESS;\r
761}\r
762\r
763EFI_STATUS\r
764EFIAPI\r
765UHCIGetState (\r
766 IN EFI_USB_HC_PROTOCOL *This,\r
767 OUT EFI_USB_HC_STATE *State\r
768 )\r
769/*++\r
770 \r
771 Routine Description:\r
772 Retrieves current state of the USB host controller.\r
773 \r
774 Arguments:\r
775 \r
776 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
777 \r
778 State A pointer to the EFI_USB_HC_STATE data structure that \r
779 indicates current state of the USB host controller. \r
780 Type EFI_USB_HC_STATE is defined below.\r
781 \r
782 typedef enum {\r
783 EfiUsbHcStateHalt,\r
784 EfiUsbHcStateOperational,\r
785 EfiUsbHcStateSuspend,\r
786 EfiUsbHcStateMaximum\r
787 } EFI_USB_HC_STATE;\r
788 \r
789 Returns:\r
790 EFI_SUCCESS \r
791 The state information of the host controller was returned in State.\r
792 EFI_INVALID_PARAMETER \r
793 State is NULL.\r
794 EFI_DEVICE_ERROR \r
795 An error was encountered while attempting to retrieve the \r
796 host controller's current state. \r
797--*/\r
798{\r
799 USB_HC_DEV *HcDev;\r
800 UINT32 CommandRegAddr;\r
801 UINT32 StatusRegAddr;\r
802 UINT16 UhcCommand;\r
803 UINT16 UhcStatus;\r
804 EFI_STATUS Status;\r
805\r
806 if (State == NULL) {\r
807 return EFI_INVALID_PARAMETER;\r
808 }\r
809\r
810 HcDev = USB_HC_DEV_FROM_THIS (This);\r
811\r
812 CommandRegAddr = (UINT32) (USBCMD);\r
813 StatusRegAddr = (UINT32) (USBSTS);\r
814\r
815 Status = ReadUHCCommandReg (\r
562d2849 816 HcDev->PciIo,\r
817 CommandRegAddr,\r
818 &UhcCommand\r
819 );\r
878ddf1f 820\r
821 if (EFI_ERROR (Status)) {\r
822 return EFI_DEVICE_ERROR;\r
823 }\r
824\r
825 Status = ReadUHCCommandReg (\r
562d2849 826 HcDev->PciIo,\r
827 StatusRegAddr,\r
828 &UhcStatus\r
829 );\r
878ddf1f 830 if (EFI_ERROR (Status)) {\r
831 return EFI_DEVICE_ERROR;\r
832 }\r
833\r
834 if (UhcCommand & USBCMD_EGSM) {\r
835 *State = EfiUsbHcStateSuspend;\r
836 return EFI_SUCCESS;\r
837 }\r
838\r
839 if ((UhcStatus & USBSTS_HCH) == 0) {\r
840 *State = EfiUsbHcStateOperational;\r
841 } else {\r
842 *State = EfiUsbHcStateHalt;\r
843 }\r
844\r
845 return EFI_SUCCESS;\r
846}\r
847\r
848\r
849EFI_STATUS\r
850EFIAPI\r
851UHCISetState (\r
852 IN EFI_USB_HC_PROTOCOL *This,\r
853 IN EFI_USB_HC_STATE State\r
854 )\r
855/*++\r
856 \r
857 Routine Description:\r
858 Sets the USB host controller to a specific state.\r
859 \r
860 Arguments:\r
861 \r
862 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
863\r
864 State Indicates the state of the host controller that will be set.\r
865 \r
866 Returns:\r
867 EFI_SUCCESS \r
868 The USB host controller was successfully placed in the state \r
869 specified by State.\r
870 EFI_INVALID_PARAMETER \r
871 State is invalid.\r
872 EFI_DEVICE_ERROR \r
873 Failed to set the state specified by State due to device error. \r
874--*/\r
875{\r
876 USB_HC_DEV *HcDev;\r
877 UINT32 CommandRegAddr;\r
878 UINT32 StatusRegAddr;\r
879 UINT16 Command;\r
880 EFI_USB_HC_STATE CurrentState;\r
881 EFI_STATUS Status;\r
882\r
883 HcDev = USB_HC_DEV_FROM_THIS (This);\r
884\r
885 CommandRegAddr = (UINT32) (USBCMD);\r
886 StatusRegAddr = (UINT32) (USBSTS);\r
887\r
888 Status = UHCIGetState (This, &CurrentState);\r
889 if (EFI_ERROR (Status)) {\r
890 return EFI_DEVICE_ERROR;\r
891 }\r
892\r
893 switch (State) {\r
894\r
895 case EfiUsbHcStateHalt:\r
896 if (CurrentState == EfiUsbHcStateHalt) {\r
897 return EFI_SUCCESS;\r
898 }\r
899\r
900 Status = ReadUHCCommandReg (\r
562d2849 901 HcDev->PciIo,\r
902 CommandRegAddr,\r
903 &Command\r
904 );\r
878ddf1f 905 if (EFI_ERROR (Status)) {\r
906 return EFI_DEVICE_ERROR;\r
907 }\r
908\r
909 Command &= ~USBCMD_RS;\r
910\r
911 Status = WriteUHCCommandReg (\r
562d2849 912 HcDev->PciIo,\r
913 CommandRegAddr,\r
914 Command\r
915 );\r
878ddf1f 916 if (EFI_ERROR (Status)) {\r
917 return EFI_DEVICE_ERROR;\r
918 }\r
919\r
920 StatusRegAddr = (UINT32) (USBSTS);\r
921 //\r
922 // ensure the HC is in halt status after send the stop command\r
923 //\r
924 if (WaitForUHCHalt (HcDev->PciIo, StatusRegAddr, STALL_1_SECOND) == EFI_TIMEOUT) {\r
925 return EFI_DEVICE_ERROR;\r
926 }\r
927 break;\r
928\r
929 case EfiUsbHcStateOperational:\r
930 if (IsHostSysOrProcessErr (HcDev->PciIo, StatusRegAddr)) {\r
931 return EFI_DEVICE_ERROR;\r
932 }\r
933\r
934 switch (CurrentState) {\r
935\r
936 case EfiUsbHcStateOperational:\r
937 return EFI_SUCCESS;\r
938\r
939 case EfiUsbHcStateHalt:\r
940 //\r
941 // Set Run/Stop bit to 1.\r
942 //\r
943 Status = ReadUHCCommandReg (\r
562d2849 944 HcDev->PciIo,\r
945 CommandRegAddr,\r
946 &Command\r
947 );\r
878ddf1f 948 if (EFI_ERROR (Status)) {\r
949 return EFI_DEVICE_ERROR;\r
950 }\r
951\r
952 Command |= USBCMD_RS | USBCMD_MAXP;\r
953 Status = WriteUHCCommandReg (\r
562d2849 954 HcDev->PciIo,\r
955 CommandRegAddr,\r
956 Command\r
957 );\r
878ddf1f 958 if (EFI_ERROR (Status)) {\r
959 return EFI_DEVICE_ERROR;\r
960 }\r
961\r
962 break;\r
963\r
964 case EfiUsbHcStateSuspend:\r
965 Status = ReadUHCCommandReg (\r
562d2849 966 HcDev->PciIo,\r
967 CommandRegAddr,\r
968 &Command\r
969 );\r
878ddf1f 970 if (EFI_ERROR (Status)) {\r
971 return EFI_DEVICE_ERROR;\r
972 }\r
973 \r
974 //\r
975 // FGR(Force Global Resume) bit is 0\r
976 //\r
977 if ((Command | (~USBCMD_FGR)) != 0xFF) {\r
978 //\r
979 // Write FGR bit to 1\r
980 //\r
981 Command |= USBCMD_FGR;\r
982 WriteUHCCommandReg (\r
983 HcDev->PciIo,\r
984 CommandRegAddr,\r
985 Command\r
986 );\r
987 }\r
988 \r
989 //\r
990 // wait 20ms to let resume complete\r
991 // (20ms is specified by UHCI spec)\r
992 //\r
993 gBS->Stall (FORCE_GLOBAL_RESUME_TIME);\r
994\r
995 //\r
996 // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0\r
997 //\r
998 Command &= ~USBCMD_FGR;\r
999 Command &= ~USBCMD_EGSM;\r
1000 Command |= USBCMD_RS;\r
1001 WriteUHCCommandReg (\r
1002 HcDev->PciIo,\r
1003 CommandRegAddr,\r
1004 Command\r
1005 );\r
1006 break;\r
1007\r
1008 default:\r
1009 break;\r
1010 }\r
1011 break;\r
1012\r
1013 case EfiUsbHcStateSuspend:\r
1014 if (CurrentState == EfiUsbHcStateSuspend) {\r
1015 return EFI_SUCCESS;\r
1016 }\r
1017\r
1018 Status = UHCISetState (This, EfiUsbHcStateHalt);\r
1019 if (EFI_ERROR (Status)) {\r
1020 return EFI_DEVICE_ERROR;\r
1021 }\r
1022 //\r
1023 // Set Enter Global Suspend Mode bit to 1.\r
1024 //\r
1025 Status = ReadUHCCommandReg (\r
562d2849 1026 HcDev->PciIo,\r
1027 CommandRegAddr,\r
1028 &Command\r
1029 );\r
878ddf1f 1030 if (EFI_ERROR (Status)) {\r
1031 return EFI_DEVICE_ERROR;\r
1032 }\r
1033\r
1034 Command |= USBCMD_EGSM;\r
1035 Status = WriteUHCCommandReg (\r
562d2849 1036 HcDev->PciIo,\r
1037 CommandRegAddr,\r
1038 Command\r
1039 );\r
878ddf1f 1040 if (EFI_ERROR (Status)) {\r
1041 return EFI_DEVICE_ERROR;\r
1042 }\r
1043 break;\r
1044\r
1045 default:\r
1046 return EFI_INVALID_PARAMETER;\r
1047 }\r
1048\r
1049 return EFI_SUCCESS;\r
1050}\r
1051\r
1052EFI_STATUS\r
1053EFIAPI\r
1054UHCIGetRootHubPortNumber (\r
1055 IN EFI_USB_HC_PROTOCOL *This,\r
1056 OUT UINT8 *PortNumber\r
1057 )\r
1058/*++\r
1059 \r
1060 Routine Description:\r
1061 Retrieves the number of root hub ports.\r
1062 \r
1063 Arguments:\r
1064 \r
1065 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1066 \r
1067 PortNumber A pointer to the number of the root hub ports.\r
1068 \r
1069 Returns:\r
1070 EFI_SUCCESS \r
1071 The port number was retrieved successfully.\r
1072 EFI_INVALID_PARAMETER \r
1073 PortNumber is NULL.\r
1074 EFI_DEVICE_ERROR \r
1075 An error was encountered while attempting to \r
1076 retrieve the port number. \r
1077--*/\r
1078{\r
1079 USB_HC_DEV *HcDev;\r
1080 UINT32 PSAddr;\r
1081 UINT16 RHPortControl;\r
1082 UINT32 Index;\r
1083 EFI_STATUS Status;\r
1084\r
1085 HcDev = USB_HC_DEV_FROM_THIS (This);\r
1086\r
1087 if (PortNumber == NULL) {\r
1088 return EFI_INVALID_PARAMETER;\r
1089 }\r
1090\r
1091 *PortNumber = 0;\r
1092\r
1093 for (Index = 0; Index < 2; Index++) {\r
1094 PSAddr = (UINT32) (USBPORTSC1 + Index * 2);\r
1095 Status = ReadRootPortReg (\r
562d2849 1096 HcDev->PciIo,\r
1097 PSAddr,\r
1098 &RHPortControl\r
1099 );\r
878ddf1f 1100 if (EFI_ERROR (Status)) {\r
1101 return EFI_DEVICE_ERROR;\r
1102 }\r
1103 //\r
1104 // Port Register content is valid\r
1105 //\r
1106 if (RHPortControl != 0xff) {\r
1107 (*PortNumber)++;\r
1108 }\r
1109 }\r
1110\r
1111 return EFI_SUCCESS;\r
1112}\r
1113\r
1114EFI_STATUS\r
1115EFIAPI\r
1116UHCIGetRootHubPortStatus (\r
1117 IN EFI_USB_HC_PROTOCOL *This,\r
1118 IN UINT8 PortNumber,\r
1119 OUT EFI_USB_PORT_STATUS *PortStatus\r
1120 )\r
1121/*++\r
1122 \r
1123 Routine Description:\r
1124 Retrieves the current status of a USB root hub port.\r
1125 \r
1126 Arguments:\r
1127 \r
1128 This A pointer to the EFI_USB_HC_PROTOCOL.\r
1129 \r
1130 PortNumber Specifies the root hub port from which the status \r
1131 is to be retrieved. This value is zero-based. For example, \r
1132 if a root hub has two ports, then the first port is numbered 0,\r
1133 and the second port is numbered 1.\r
1134 \r
1135 PortStatus A pointer to the current port status bits and \r
1136 port status change bits. \r
1137 \r
1138 Returns:\r
1139 EFI_SUCCESS \r
1140 The status of the USB root hub port specified by PortNumber \r
1141 was returned in PortStatus.\r
1142 EFI_INVALID_PARAMETER \r
1143 PortNumber is invalid. \r
1144 EFI_DEVICE_ERROR - Can't read register \r
1145--*/\r
1146{\r
1147 USB_HC_DEV *HcDev;\r
1148 UINT32 PSAddr;\r
1149 UINT16 RHPortStatus;\r
1150 UINT8 TotalPortNumber;\r
1151 EFI_STATUS Status;\r
1152\r
1153 if (PortStatus == NULL) {\r
1154 return EFI_INVALID_PARAMETER;\r
1155 }\r
1156\r
1157 UHCIGetRootHubPortNumber (This, &TotalPortNumber);\r
1158 if (PortNumber >= TotalPortNumber) {\r
1159 return EFI_INVALID_PARAMETER;\r
1160 }\r
1161\r
1162 HcDev = USB_HC_DEV_FROM_THIS (This);\r
1163 PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);\r
1164\r
1165 //\r
1166 // Clear port status\r
1167 //\r
1168 PortStatus->PortStatus = 0;\r
1169 PortStatus->PortChangeStatus = 0;\r
1170\r
1171 Status = ReadRootPortReg (\r
562d2849 1172 HcDev->PciIo,\r
1173 PSAddr,\r
1174 &RHPortStatus\r
1175 );\r
878ddf1f 1176\r
1177 if (EFI_ERROR (Status)) {\r
1178 return EFI_DEVICE_ERROR;\r
1179 }\r
1180 //\r
1181 // Fill Port Status bits\r
1182 //\r
1183 \r
1184 //\r
1185 // Current Connect Status\r
1186 //\r
1187 if (RHPortStatus & USBPORTSC_CCS) {\r
1188 PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;\r
1189 }\r
1190 //\r
1191 // Port Enabled/Disabled\r
1192 //\r
1193 if (RHPortStatus & USBPORTSC_PED) {\r
1194 PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;\r
1195 }\r
1196 \r
1197 //\r
1198 // Port Suspend\r
1199 //\r
1200 if (RHPortStatus & USBPORTSC_SUSP) {\r
1201 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
1202 }\r
1203 \r
1204 //\r
1205 // Port Reset\r
1206 //\r
1207 if (RHPortStatus & USBPORTSC_PR) {\r
1208 PortStatus->PortStatus |= USB_PORT_STAT_RESET;\r
1209 }\r
1210 \r
1211 //\r
1212 // Low Speed Device Attached\r
1213 //\r
1214 if (RHPortStatus & USBPORTSC_LSDA) {\r
1215 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
1216 }\r
1217 //\r
562d2849 1218 // CHC will always return one in this bit\r
1219 //\r
1220 PortStatus->PortStatus |= USB_PORT_STAT_OWNER;\r
1221 //\r
878ddf1f 1222 // Fill Port Status Change bits\r
1223 //\r
1224 \r
1225 //\r
1226 // Connect Status Change\r
1227 //\r
1228 if (RHPortStatus & USBPORTSC_CSC) {\r
1229 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;\r
1230 }\r
1231 \r
1232 //\r
1233 // Port Enabled/Disabled Change\r
1234 //\r
1235 if (RHPortStatus & USBPORTSC_PEDC) {\r
1236 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;\r
1237 }\r
1238\r
1239 return EFI_SUCCESS;\r
1240}\r
1241\r
1242EFI_STATUS\r
1243EFIAPI\r
1244UHCISetRootHubPortFeature (\r
1245 IN EFI_USB_HC_PROTOCOL *This,\r
1246 IN UINT8 PortNumber,\r
1247 IN EFI_USB_PORT_FEATURE PortFeature\r
1248 )\r
1249/*++\r
1250 \r
1251 Routine Description:\r
1252 Sets a feature for the specified root hub port.\r
1253 \r
1254 Arguments:\r
1255 \r
1256 This A pointer to the EFI_USB_HC_PROTOCOL.\r
1257 \r
1258 PortNumber Specifies the root hub port whose feature \r
1259 is requested to be set.\r
1260 \r
1261 PortFeature Indicates the feature selector associated \r
1262 with the feature set request. \r
1263 \r
1264 Returns:\r
1265 EFI_SUCCESS \r
1266 The feature specified by PortFeature was set for the \r
1267 USB root hub port specified by PortNumber.\r
1268 EFI_INVALID_PARAMETER \r
1269 PortNumber is invalid or PortFeature is invalid.\r
1270 EFI_DEVICE_ERROR\r
1271 Can't read register\r
1272--*/\r
1273{\r
1274 USB_HC_DEV *HcDev;\r
1275 UINT32 PSAddr;\r
1276 UINT32 CommandRegAddr;\r
1277 //\r
1278 // root hub port status\r
1279 //\r
1280 UINT16 RHPortControl;\r
1281 UINT16 Command;\r
1282 UINT8 TotalPortNumber;\r
1283 EFI_STATUS Status;\r
1284\r
1285 UHCIGetRootHubPortNumber (This, &TotalPortNumber);\r
1286 if (PortNumber >= TotalPortNumber) {\r
1287 return EFI_INVALID_PARAMETER;\r
1288 }\r
1289\r
1290 HcDev = USB_HC_DEV_FROM_THIS (This);\r
1291\r
1292 PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);\r
1293 CommandRegAddr = (UINT32) (USBCMD);\r
1294\r
1295 Status = ReadRootPortReg (\r
1296 HcDev->PciIo,\r
1297 PSAddr,\r
1298 &RHPortControl\r
1299 );\r
1300 if (EFI_ERROR (Status)) {\r
1301 return EFI_DEVICE_ERROR;\r
1302 }\r
1303\r
1304 switch (PortFeature) {\r
1305\r
1306 case EfiUsbPortSuspend:\r
1307 Status = ReadUHCCommandReg (\r
562d2849 1308 HcDev->PciIo,\r
1309 CommandRegAddr,\r
1310 &Command\r
1311 );\r
878ddf1f 1312 if (EFI_ERROR (Status)) {\r
1313 return EFI_DEVICE_ERROR;\r
1314 }\r
1315\r
1316 if (!(Command & USBCMD_EGSM)) {\r
1317 //\r
1318 // if global suspend is not active, can set port suspend\r
1319 //\r
1320 RHPortControl &= 0xfff5;\r
1321 RHPortControl |= USBPORTSC_SUSP;\r
1322 }\r
1323 break;\r
1324\r
1325 case EfiUsbPortReset:\r
1326 RHPortControl &= 0xfff5;\r
1327 //\r
1328 // Set the reset bit\r
1329 //\r
1330 RHPortControl |= USBPORTSC_PR;\r
1331 break;\r
1332\r
1333 case EfiUsbPortPower:\r
1334 break;\r
1335\r
1336 case EfiUsbPortEnable:\r
1337 RHPortControl &= 0xfff5;\r
1338 RHPortControl |= USBPORTSC_PED;\r
1339 break;\r
1340\r
1341 default:\r
1342 return EFI_INVALID_PARAMETER;\r
1343 }\r
1344\r
1345 WriteRootPortReg (\r
1346 HcDev->PciIo,\r
1347 PSAddr,\r
1348 RHPortControl\r
1349 );\r
1350\r
1351 return EFI_SUCCESS;\r
1352}\r
1353\r
1354EFI_STATUS\r
1355EFIAPI\r
1356UHCIClearRootHubPortFeature (\r
1357 IN EFI_USB_HC_PROTOCOL *This,\r
1358 IN UINT8 PortNumber,\r
1359 IN EFI_USB_PORT_FEATURE PortFeature\r
1360 )\r
1361/*++\r
1362 \r
1363 Routine Description:\r
1364 Clears a feature for the specified root hub port.\r
1365 \r
1366 Arguments:\r
1367 \r
1368 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1369 \r
1370 PortNumber Specifies the root hub port whose feature \r
1371 is requested to be cleared.\r
1372 \r
1373 PortFeature Indicates the feature selector associated with the \r
1374 feature clear request.\r
1375 \r
1376 Returns:\r
1377 EFI_SUCCESS \r
1378 The feature specified by PortFeature was cleared for the \r
1379 USB root hub port specified by PortNumber.\r
1380 EFI_INVALID_PARAMETER \r
1381 PortNumber is invalid or PortFeature is invalid.\r
1382 EFI_DEVICE_ERROR\r
1383 Can't read register\r
1384--*/\r
1385{\r
1386 USB_HC_DEV *HcDev;\r
1387 UINT32 PSAddr;\r
1388 UINT16 RHPortControl;\r
1389 UINT8 TotalPortNumber;\r
1390 EFI_STATUS Status;\r
1391\r
1392 UHCIGetRootHubPortNumber (This, &TotalPortNumber);\r
1393\r
1394 if (PortNumber >= TotalPortNumber) {\r
1395 return EFI_INVALID_PARAMETER;\r
1396 }\r
1397\r
1398 HcDev = USB_HC_DEV_FROM_THIS (This);\r
1399 PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);\r
1400\r
1401 Status = ReadRootPortReg (\r
562d2849 1402 HcDev->PciIo,\r
1403 PSAddr,\r
1404 &RHPortControl\r
1405 );\r
878ddf1f 1406 if (EFI_ERROR (Status)) {\r
1407 return EFI_DEVICE_ERROR;\r
1408 }\r
1409\r
1410 switch (PortFeature) {\r
1411 //\r
1412 // clear PORT_ENABLE feature means disable port.\r
1413 //\r
1414 case EfiUsbPortEnable:\r
1415 RHPortControl &= 0xfff5;\r
1416 RHPortControl &= ~USBPORTSC_PED;\r
1417 break;\r
1418\r
1419 //\r
1420 // clear PORT_SUSPEND feature means resume the port.\r
1421 // (cause a resume on the specified port if in suspend mode)\r
1422 //\r
1423 case EfiUsbPortSuspend:\r
1424 RHPortControl &= 0xfff5;\r
1425 RHPortControl &= ~USBPORTSC_SUSP;\r
1426 break;\r
1427\r
1428 //\r
1429 // no operation\r
1430 //\r
1431 case EfiUsbPortPower:\r
1432 break;\r
1433\r
1434 //\r
1435 // clear PORT_RESET means clear the reset signal.\r
1436 //\r
1437 case EfiUsbPortReset:\r
1438 RHPortControl &= 0xfff5;\r
1439 RHPortControl &= ~USBPORTSC_PR;\r
1440 break;\r
1441\r
1442 //\r
1443 // clear connect status change\r
1444 //\r
1445 case EfiUsbPortConnectChange:\r
1446 RHPortControl &= 0xfff5;\r
1447 RHPortControl |= USBPORTSC_CSC;\r
1448 break;\r
1449\r
1450 //\r
1451 // clear enable/disable status change\r
1452 //\r
1453 case EfiUsbPortEnableChange:\r
1454 RHPortControl &= 0xfff5;\r
1455 RHPortControl |= USBPORTSC_PEDC;\r
1456 break;\r
1457\r
1458 //\r
1459 // root hub does not support this request\r
1460 //\r
1461 case EfiUsbPortSuspendChange:\r
1462 break;\r
1463\r
1464 //\r
1465 // root hub does not support this request\r
1466 //\r
1467 case EfiUsbPortOverCurrentChange:\r
1468 break;\r
1469\r
1470 //\r
1471 // root hub does not support this request\r
1472 //\r
1473 case EfiUsbPortResetChange:\r
1474 break;\r
1475\r
1476 default:\r
1477 return EFI_INVALID_PARAMETER;\r
1478 }\r
1479\r
1480 WriteRootPortReg (\r
1481 HcDev->PciIo,\r
1482 PSAddr,\r
1483 RHPortControl\r
1484 );\r
1485\r
1486 return EFI_SUCCESS;\r
1487}\r
1488\r
1489EFI_STATUS\r
1490EFIAPI\r
1491UHCIControlTransfer (\r
1492 IN EFI_USB_HC_PROTOCOL *This,\r
1493 IN UINT8 DeviceAddress,\r
1494 IN BOOLEAN IsSlowDevice,\r
1495 IN UINT8 MaximumPacketLength,\r
1496 IN EFI_USB_DEVICE_REQUEST *Request,\r
1497 IN EFI_USB_DATA_DIRECTION TransferDirection,\r
1498 IN OUT VOID *Data, OPTIONAL\r
1499 IN OUT UINTN *DataLength, OPTIONAL\r
1500 IN UINTN TimeOut,\r
1501 OUT UINT32 *TransferResult\r
1502 )\r
1503/*++\r
1504 \r
1505 Routine Description:\r
1506 Submits control transfer to a target USB device.\r
1507 \r
1508 Arguments:\r
1509 \r
1510 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1511\r
1512 DeviceAddress Represents the address of the target device on the USB,\r
1513 which is assigned during USB enumeration.\r
1514\r
1515 IsSlowDevice Indicates whether the target device is slow device \r
1516 or full-speed device.\r
1517 \r
1518 MaximumPacketLength Indicates the maximum packet size that the \r
1519 default control transfer endpoint is capable of \r
1520 sending or receiving.\r
1521 \r
1522 Request A pointer to the USB device request that will be sent \r
1523 to the USB device. \r
1524 \r
1525 TransferDirection Specifies the data direction for the transfer.\r
1526 There are three values available, DataIn, DataOut \r
1527 and NoData.\r
1528 \r
1529 Data A pointer to the buffer of data that will be transmitted \r
1530 to USB device or received from USB device.\r
1531 \r
1532 DataLength Indicates the size, in bytes, of the data buffer \r
1533 specified by Data.\r
1534 \r
1535 TimeOut Indicates the maximum time, in microseconds, \r
1536 which the transfer is allowed to complete.\r
1537 \r
1538 TransferResult A pointer to the detailed result information generated \r
1539 by this control transfer.\r
1540 \r
1541 Returns:\r
1542 EFI_SUCCESS \r
1543 The control transfer was completed successfully.\r
1544 EFI_OUT_OF_RESOURCES \r
1545 The control transfer could not be completed due to a lack of resources.\r
1546 EFI_INVALID_PARAMETER \r
1547 Some parameters are invalid.\r
1548 EFI_TIMEOUT \r
1549 The control transfer failed due to timeout.\r
1550 EFI_DEVICE_ERROR \r
1551 The control transfer failed due to host controller or device error. \r
1552 Caller should check TranferResult for detailed error information.\r
1553\r
1554--*/\r
1555{\r
1556 USB_HC_DEV *HcDev;\r
1557 UINT32 StatusReg;\r
1558 UINT32 FrameNumReg;\r
1559 UINT8 PktID;\r
1560 QH_STRUCT *PtrQH;\r
1561 TD_STRUCT *PtrTD;\r
1562 TD_STRUCT *PtrPreTD;\r
1563 TD_STRUCT *PtrSetupTD;\r
1564 TD_STRUCT *PtrStatusTD;\r
1565 EFI_STATUS Status;\r
1566 UINTN Index;\r
1567 UINTN DataLen;\r
1568 UINT8 *PtrDataSource;\r
1569 UINT8 *Ptr;\r
1570 UINT8 DataToggle;\r
1571 UINT16 LoadFrameListIndex;\r
1572 UINT8 PktSize;\r
1573\r
1574 UINT8 *RequestMappedAddress;\r
1575 VOID *RequestMapping;\r
1576 UINTN RequestLen;\r
1577\r
1578 EFI_PHYSICAL_ADDRESS TempPtr;\r
1579 VOID *Mapping;\r
1580\r
1581 TD_STRUCT *PtrFirstDataTD;\r
1582 TD_STRUCT *ptrLastDataTD;\r
1583 BOOLEAN FirstTD;\r
1584\r
1585 FirstTD = FALSE;\r
1586 RequestMappedAddress = NULL;\r
1587 RequestMapping = NULL;\r
1588 Mapping = NULL;\r
1589 PtrFirstDataTD = NULL;\r
1590 ptrLastDataTD = NULL;\r
1591 PktID = INPUT_PACKET_ID;\r
1592 Mapping = NULL;\r
1593 HcDev = USB_HC_DEV_FROM_THIS (This);\r
1594 StatusReg = (UINT32) (USBSTS);\r
1595 FrameNumReg = (UINT32) (USBFRNUM);\r
1596 PtrPreTD = NULL;\r
1597 PtrTD = NULL;\r
1598\r
1599 //\r
1600 // Parameters Checking\r
1601 //\r
1602 if (Request == NULL || TransferResult == NULL) {\r
1603 return EFI_INVALID_PARAMETER;\r
1604 }\r
1605 \r
1606 //\r
1607 // if errors exist that cause host controller halt,\r
1608 // then return EFI_DEVICE_ERROR.\r
1609 //\r
1610 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
1611\r
1612 ClearStatusReg (HcDev->PciIo, StatusReg);\r
1613 *TransferResult = EFI_USB_ERR_SYSTEM;\r
1614 return EFI_DEVICE_ERROR;\r
1615 }\r
1616 \r
1617 //\r
1618 // low speed usb devices are limited to only an eight-byte\r
1619 // maximum data payload size\r
1620 //\r
1621 if (IsSlowDevice && (MaximumPacketLength != 8)) {\r
1622 return EFI_INVALID_PARAMETER;\r
1623 }\r
1624\r
1625 if (MaximumPacketLength != 8 && \r
1626 MaximumPacketLength != 16 &&\r
1627 MaximumPacketLength != 32 &&\r
1628 MaximumPacketLength != 64) {\r
1629 return EFI_INVALID_PARAMETER;\r
1630 }\r
1631\r
1632 if ((TransferDirection != EfiUsbNoData) && (DataLength == NULL)) {\r
1633 return EFI_INVALID_PARAMETER;\r
1634 }\r
1635\r
1636 switch (TransferDirection) {\r
1637\r
1638 case EfiUsbDataIn:\r
1639 PktID = INPUT_PACKET_ID;\r
1640 PtrDataSource = Data;\r
1641 DataLen = *DataLength;\r
1642\r
1643 //\r
1644 // map the source data buffer for bus master access.\r
1645 // BusMasterWrite means cpu read\r
1646 //\r
1647 Status = HcDev->PciIo->Map (\r
562d2849 1648 HcDev->PciIo,\r
1649 EfiPciIoOperationBusMasterWrite,\r
1650 PtrDataSource,\r
1651 &DataLen,\r
1652 &TempPtr,\r
1653 &Mapping\r
1654 );\r
878ddf1f 1655 if (EFI_ERROR (Status)) {\r
1656 return Status;\r
1657 }\r
1658\r
1659 Ptr = (UINT8 *) ((UINTN) TempPtr);\r
1660 break;\r
1661\r
1662 case EfiUsbDataOut:\r
1663 PktID = OUTPUT_PACKET_ID;\r
1664 PtrDataSource = Data;\r
1665 DataLen = *DataLength;\r
1666\r
1667 //\r
1668 // map the source data buffer for bus master access.\r
1669 // BusMasterRead means cpu write\r
1670 //\r
1671 Status = HcDev->PciIo->Map (\r
562d2849 1672 HcDev->PciIo,\r
1673 EfiPciIoOperationBusMasterRead,\r
1674 PtrDataSource,\r
1675 &DataLen,\r
1676 &TempPtr,\r
1677 &Mapping\r
1678 );\r
878ddf1f 1679 if (EFI_ERROR (Status)) {\r
1680 return Status;\r
1681 }\r
1682\r
1683 Ptr = (UINT8 *) ((UINTN) TempPtr);\r
1684 break;\r
1685\r
1686 //\r
1687 // no data stage\r
1688 //\r
1689 case EfiUsbNoData:\r
1690 if ((DataLength != NULL) && (*DataLength != 0)) {\r
1691 return EFI_INVALID_PARAMETER;\r
1692 }\r
1693\r
1694 PktID = OUTPUT_PACKET_ID;\r
1695 PtrDataSource = NULL;\r
1696 DataLen = 0;\r
1697 Ptr = NULL;\r
1698 break;\r
1699\r
1700 default:\r
1701 return EFI_INVALID_PARAMETER;\r
1702 }\r
1703\r
1704 Status = ClearStatusReg (HcDev->PciIo, StatusReg);\r
1705 if (EFI_ERROR (Status)) {\r
1706 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
1707 return EFI_DEVICE_ERROR;\r
1708 }\r
1709 //\r
1710 // create QH structure and init\r
1711 //\r
1712 Status = CreateQH (HcDev, &PtrQH);\r
1713 if (EFI_ERROR (Status)) {\r
1714 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
1715 return Status;\r
1716 }\r
1717 \r
1718 //\r
1719 // map the Request for bus master access.\r
1720 // BusMasterRead means cpu write\r
1721 //\r
1722 RequestLen = sizeof (EFI_USB_DEVICE_REQUEST);\r
1723 Status = HcDev->PciIo->Map (\r
562d2849 1724 HcDev->PciIo,\r
1725 EfiPciIoOperationBusMasterRead,\r
1726 (UINT8 *) Request,\r
1727 &RequestLen,\r
1728 &TempPtr,\r
1729 &RequestMapping\r
1730 );\r
878ddf1f 1731\r
1732 if (EFI_ERROR (Status)) {\r
1733 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
1734 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
1735 return Status;\r
1736 }\r
1737\r
1738 RequestMappedAddress = (UINT8 *) ((UINTN) TempPtr);\r
1739\r
1740 //\r
1741 // generate Setup Stage TD\r
1742 //\r
1743 Status = GenSetupStageTD (\r
562d2849 1744 HcDev,\r
1745 DeviceAddress,\r
1746 0,\r
1747 IsSlowDevice,\r
1748 (UINT8 *) RequestMappedAddress,\r
1749 sizeof (EFI_USB_DEVICE_REQUEST),\r
1750 &PtrSetupTD\r
1751 );\r
878ddf1f 1752\r
1753 if (EFI_ERROR (Status)) {\r
1754 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
1755 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
1756 HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);\r
1757 return Status;\r
1758 }\r
1759 \r
1760 //\r
1761 // Data Stage of Control Transfer\r
1762 //\r
1763 DataToggle = 1;\r
1764 FirstTD = TRUE;\r
1765 while (DataLen > 0) {\r
1766 //\r
1767 // create TD structures and link together\r
1768 //\r
1769 \r
1770 //\r
1771 // PktSize is the data load size that each TD carries.\r
1772 //\r
1773 PktSize = (UINT8) DataLen;\r
1774 if (DataLen > MaximumPacketLength) {\r
1775 PktSize = MaximumPacketLength;\r
1776 }\r
1777\r
1778 Status = GenDataTD (\r
562d2849 1779 HcDev,\r
1780 DeviceAddress,\r
1781 0,\r
1782 Ptr,\r
1783 PktSize,\r
1784 PktID,\r
1785 DataToggle,\r
1786 IsSlowDevice,\r
1787 &PtrTD\r
1788 );\r
878ddf1f 1789\r
1790 if (EFI_ERROR (Status)) {\r
1791 //\r
1792 // free all resources occupied\r
1793 //\r
1794 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
1795 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
1796 HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);\r
1797 DeleteQueuedTDs (HcDev, PtrSetupTD);\r
1798 DeleteQueuedTDs (HcDev, PtrFirstDataTD);\r
1799 return Status;\r
1800 }\r
1801 \r
1802 //\r
1803 // Link two TDs in vertical depth\r
1804 //\r
1805 if (FirstTD) {\r
1806 PtrFirstDataTD = PtrTD;\r
1807 PtrFirstDataTD->ptrNextTD = NULL;\r
1808 FirstTD = FALSE;\r
1809 } else {\r
1810 LinkTDToTD (PtrPreTD, PtrTD);\r
1811 }\r
1812\r
1813 PtrPreTD = PtrTD;\r
1814\r
1815 DataToggle ^= 1;\r
1816 Ptr += PktSize;\r
1817 DataLen -= PktSize;\r
1818 }\r
1819\r
1820 ptrLastDataTD = PtrTD;\r
1821\r
1822 //\r
1823 // Status Stage of Control Transfer\r
1824 //\r
1825 if (PktID == OUTPUT_PACKET_ID) {\r
1826 PktID = INPUT_PACKET_ID;\r
1827 } else {\r
1828 PktID = OUTPUT_PACKET_ID;\r
1829 }\r
1830 \r
1831 //\r
1832 // create Status Stage TD structure\r
1833 //\r
1834 Status = CreateStatusTD (\r
562d2849 1835 HcDev,\r
1836 DeviceAddress,\r
1837 0,\r
1838 PktID,\r
1839 IsSlowDevice,\r
1840 &PtrStatusTD\r
1841 );\r
878ddf1f 1842\r
1843 if (EFI_ERROR (Status)) {\r
1844 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
1845 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
1846 HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);\r
1847 DeleteQueuedTDs (HcDev, PtrSetupTD);\r
1848 DeleteQueuedTDs (HcDev, PtrFirstDataTD);\r
1849 return Status;\r
1850 }\r
1851\r
1852 if (IsSlowDevice) {\r
1853 //\r
1854 // link setup TD structures to QH structure\r
1855 //\r
1856 LinkTDToQH (PtrQH, PtrSetupTD);\r
1857\r
1858 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
1859\r
1860 //\r
1861 // link QH-TDs to total 100 frame list entry to speed up the execution.\r
1862 //\r
1863 for (Index = 0; Index < 100; Index++) {\r
1864 LinkQHToFrameList (\r
1865 HcDev->FrameListEntry,\r
1866 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
1867 PtrQH\r
1868 );\r
1869 }\r
1870 //\r
1871 // Poll QH-TDs execution and get result.\r
1872 // detail status is returned\r
1873 //\r
1874 Status = ExecuteControlTransfer (\r
1875 HcDev,\r
1876 PtrSetupTD,\r
1877 LoadFrameListIndex,\r
1878 DataLength,\r
1879 TimeOut,\r
1880 TransferResult\r
1881 );\r
1882 //\r
1883 // Remove Control Transfer QH-TDs structure from the frame list\r
1884 // and update the pointers in the Frame List\r
1885 // and other pointers in other related QH structures.\r
1886 //\r
1887 for (Index = 0; Index < 100; Index++) {\r
1888 DelLinkSingleQH (\r
1889 HcDev,\r
1890 PtrQH,\r
1891 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
1892 FALSE,\r
1893 FALSE\r
1894 );\r
1895 }\r
1896 //\r
1897 // delete setup stage TD; the QH is reserved for the next stages.\r
1898 //\r
1899 DeleteQueuedTDs (HcDev, PtrSetupTD);\r
1900\r
1901 //\r
1902 // if setup stage error, return error\r
1903 //\r
1904 if (EFI_ERROR (Status)) {\r
1905 goto Done;\r
1906 }\r
1907 //\r
1908 // some control transfers do not have Data Stage\r
1909 //\r
1910 if (PtrFirstDataTD != NULL) {\r
1911\r
1912 LinkTDToQH (PtrQH, PtrFirstDataTD);\r
1913 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
1914\r
1915 for (Index = 0; Index < 500; Index++) {\r
1916 LinkQHToFrameList (\r
1917 HcDev->FrameListEntry,\r
1918 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
1919 PtrQH\r
1920 );\r
1921 }\r
1922\r
1923 Status = ExecuteControlTransfer (\r
562d2849 1924 HcDev,\r
1925 PtrFirstDataTD,\r
1926 LoadFrameListIndex,\r
1927 DataLength,\r
1928 TimeOut,\r
1929 TransferResult\r
1930 );\r
878ddf1f 1931\r
1932 for (Index = 0; Index < 500; Index++) {\r
1933 DelLinkSingleQH (\r
1934 HcDev,\r
1935 PtrQH,\r
1936 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
1937 FALSE,\r
1938 FALSE\r
1939 );\r
1940 }\r
1941 //\r
1942 // delete data stage TD; the QH is reserved for the next stage.\r
1943 //\r
1944 DeleteQueuedTDs (HcDev, PtrFirstDataTD);\r
1945 }\r
1946 //\r
1947 // if data stage error, goto done and return error\r
1948 //\r
1949 if (EFI_ERROR (Status)) {\r
1950 goto Done;\r
1951 }\r
1952\r
1953 LinkTDToQH (PtrQH, PtrStatusTD);\r
1954 //\r
1955 // get the frame list index that the QH-TDs will be linked to.\r
1956 //\r
1957 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
1958\r
1959 for (Index = 0; Index < 100; Index++) {\r
1960 //\r
1961 // put the QH-TDs directly or indirectly into the proper place\r
1962 // in the Frame List\r
1963 //\r
1964 LinkQHToFrameList (\r
1965 HcDev->FrameListEntry,\r
1966 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
1967 PtrQH\r
1968 );\r
1969 }\r
1970 //\r
1971 // Poll QH-TDs execution and get result.\r
1972 // detail status is returned\r
1973 //\r
1974 Status = ExecuteControlTransfer (\r
562d2849 1975 HcDev,\r
1976 PtrStatusTD,\r
1977 LoadFrameListIndex,\r
1978 DataLength,\r
1979 TimeOut,\r
1980 TransferResult\r
1981 );\r
878ddf1f 1982\r
1983 //\r
1984 // Delete Control Transfer QH-TDs structure\r
1985 // and update the pointers in the Frame List\r
1986 // and other pointers in other related QH structures.\r
1987 //\r
1988 // TRUE means must search other framelistindex\r
1989 //\r
1990 for (Index = 0; Index < 100; Index++) {\r
1991 DelLinkSingleQH (\r
1992 HcDev,\r
1993 PtrQH,\r
1994 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
1995 FALSE,\r
1996 FALSE\r
1997 );\r
1998 }\r
1999\r
2000 DeleteQueuedTDs (HcDev, PtrStatusTD);\r
2001\r
2002 } else {\r
2003 //\r
2004 // link setup stage TD with data stage TD\r
2005 //\r
2006 PtrPreTD = PtrSetupTD;\r
2007 if (PtrFirstDataTD != NULL) {\r
2008 LinkTDToTD (PtrSetupTD, PtrFirstDataTD);\r
2009 PtrPreTD = ptrLastDataTD;\r
2010 }\r
2011 //\r
2012 // link status TD with previous TD\r
2013 //\r
2014 LinkTDToTD (PtrPreTD, PtrStatusTD);\r
2015\r
2016 //\r
2017 // link QH with TD\r
2018 //\r
2019 LinkTDToQH (PtrQH, PtrSetupTD);\r
2020\r
2021 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
2022 for (Index = 0; Index < 500; Index++) {\r
2023 //\r
2024 // put the QH-TDs directly or indirectly into the proper place\r
2025 // in the Frame List\r
2026 //\r
2027 LinkQHToFrameList (\r
2028 HcDev->FrameListEntry,\r
2029 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
2030 PtrQH\r
2031 );\r
2032 }\r
2033 //\r
2034 // Poll QH-TDs execution and get result.\r
2035 // detail status is returned\r
2036 //\r
2037 Status = ExecuteControlTransfer (\r
562d2849 2038 HcDev,\r
2039 PtrSetupTD,\r
2040 LoadFrameListIndex,\r
2041 DataLength,\r
2042 TimeOut,\r
2043 TransferResult\r
2044 );\r
878ddf1f 2045 //\r
2046 // Remove Control Transfer QH-TDs structure from the frame list\r
2047 // and update the pointers in the Frame List\r
2048 // and other pointers in other related QH structures.\r
2049 //\r
2050 for (Index = 0; Index < 500; Index++) {\r
2051 DelLinkSingleQH (\r
2052 HcDev,\r
2053 PtrQH,\r
2054 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
2055 FALSE,\r
2056 FALSE\r
2057 );\r
2058 }\r
2059\r
2060 DeleteQueuedTDs (HcDev, PtrSetupTD);\r
2061 }\r
2062\r
2063Done:\r
2064\r
2065 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
2066\r
2067 if (Mapping != NULL) {\r
2068 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2069 }\r
2070\r
2071 if (RequestMapping != NULL) {\r
2072 HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);\r
2073 }\r
2074 //\r
2075 // if has errors that cause host controller halt,\r
2076 // then return EFI_DEVICE_ERROR directly.\r
2077 //\r
2078 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
2079\r
2080 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2081 *TransferResult |= EFI_USB_ERR_SYSTEM;\r
2082 return EFI_DEVICE_ERROR;\r
2083 }\r
2084\r
2085 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2086 HcDev->PciIo->Flush (HcDev->PciIo);\r
2087 return Status;\r
2088}\r
2089\r
2090EFI_STATUS\r
2091EFIAPI\r
2092UHCIBulkTransfer (\r
2093 IN EFI_USB_HC_PROTOCOL *This,\r
2094 IN UINT8 DeviceAddress,\r
2095 IN UINT8 EndPointAddress,\r
2096 IN UINT8 MaximumPacketLength,\r
2097 IN OUT VOID *Data,\r
2098 IN OUT UINTN *DataLength,\r
2099 IN OUT UINT8 *DataToggle,\r
2100 IN UINTN TimeOut,\r
2101 OUT UINT32 *TransferResult\r
2102 )\r
2103/*++\r
2104 \r
2105 Routine Description:\r
2106 Submits bulk transfer to a bulk endpoint of a USB device.\r
2107 \r
2108 Arguments:\r
2109 \r
2110 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
2111 \r
2112 DeviceAddress Represents the address of the target device on the USB,\r
2113 which is assigned during USB enumeration.\r
2114 EndPointAddress The combination of an endpoint number and an \r
2115 endpoint direction of the target USB device. \r
2116 Each endpoint address supports data transfer in \r
2117 one direction except the control endpoint \r
2118 (whose default endpoint address is 0). \r
2119 It is the caller's responsibility to make sure that \r
2120 the EndPointAddress represents a bulk endpoint. \r
2121 \r
2122 MaximumPacketLength Indicates the maximum packet size the target endpoint\r
2123 is capable of sending or receiving.\r
2124 \r
2125 Data A pointer to the buffer of data that will be transmitted \r
2126 to USB device or received from USB device.\r
2127 DataLength When input, indicates the size, in bytes, of the data buffer\r
2128 specified by Data. When output, indicates the actually \r
2129 transferred data size.\r
2130 \r
2131 DataToggle A pointer to the data toggle value. On input, it indicates \r
2132 the initial data toggle value the bulk transfer should adopt;\r
2133 on output, it is updated to indicate the data toggle value \r
2134 of the subsequent bulk transfer. \r
2135 \r
2136 TimeOut Indicates the maximum time, in microseconds, which the \r
2137 transfer is allowed to complete.\r
2138 \r
2139 TransferResult A pointer to the detailed result information of the \r
2140 bulk transfer.\r
2141\r
2142 Returns:\r
2143 EFI_SUCCESS \r
2144 The bulk transfer was completed successfully.\r
2145 EFI_OUT_OF_RESOURCES \r
2146 The bulk transfer could not be submitted due to lack of resource.\r
2147 EFI_INVALID_PARAMETER \r
2148 Some parameters are invalid.\r
2149 EFI_TIMEOUT \r
2150 The bulk transfer failed due to timeout.\r
2151 EFI_DEVICE_ERROR \r
2152 The bulk transfer failed due to host controller or device error.\r
2153 Caller should check TranferResult for detailed error information.\r
2154\r
2155--*/\r
2156{\r
2157 USB_HC_DEV *HcDev;\r
2158 UINT32 StatusReg;\r
2159 UINT32 FrameNumReg;\r
2160 UINTN DataLen;\r
2161 QH_STRUCT *PtrQH;\r
2162 TD_STRUCT *PtrFirstTD;\r
2163 TD_STRUCT *PtrTD;\r
2164 TD_STRUCT *PtrPreTD;\r
2165 UINT16 LoadFrameListIndex;\r
2166 UINT16 SavedFrameListIndex;\r
2167 UINT8 PktID;\r
2168 UINT8 *PtrDataSource;\r
2169 UINT8 *Ptr;\r
2170 BOOLEAN IsFirstTD;\r
2171 EFI_STATUS Status;\r
2172 UINT32 Index;\r
2173 UINT8 PktSize;\r
2174\r
2175 EFI_USB_DATA_DIRECTION TransferDirection;\r
2176 //\r
2177 // Used to calculate how many entries are linked to the\r
2178 // specified bulk transfer QH-TDs\r
2179 //\r
2180 UINT32 LinkTimes;\r
2181\r
2182 BOOLEAN ShortPacketEnable;\r
2183 EFI_PHYSICAL_ADDRESS TempPtr;\r
2184 VOID *Mapping;\r
2185\r
2186 HcDev = USB_HC_DEV_FROM_THIS (This);\r
2187 StatusReg = (UINT32) (USBSTS);\r
2188 FrameNumReg = (UINT32) (USBFRNUM);\r
2189 PktID = INPUT_PACKET_ID;\r
2190 PtrTD = NULL;\r
2191 PtrFirstTD = NULL;\r
2192 PtrPreTD = NULL;\r
2193 LinkTimes = 1;\r
2194 DataLen = 0;\r
2195 Ptr = NULL;\r
2196 ShortPacketEnable = FALSE;\r
2197 Mapping = NULL;\r
2198\r
2199 //\r
2200 // Parameters Checking\r
2201 //\r
2202 \r
2203 if ((DataLength == NULL) ||\r
2204 (Data == NULL) ||\r
2205 (TransferResult == NULL)) {\r
2206 return EFI_INVALID_PARAMETER;\r
2207 }\r
2208 \r
2209 //\r
2210 // if has errors that cause host controller halt,\r
2211 // then return EFI_DEVICE_ERROR directly.\r
2212 //\r
2213 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
2214\r
2215 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2216 *TransferResult = EFI_USB_ERR_SYSTEM;\r
2217 return EFI_DEVICE_ERROR;\r
2218 }\r
2219\r
2220 if (*DataLength == 0) {\r
2221 return EFI_INVALID_PARAMETER;\r
2222 }\r
2223\r
2224 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
2225 return EFI_INVALID_PARAMETER;\r
2226 }\r
2227\r
2228 if (MaximumPacketLength != 8 &&\r
2229 MaximumPacketLength != 16 &&\r
2230 MaximumPacketLength != 32 &&\r
2231 MaximumPacketLength != 64) {\r
2232 return EFI_INVALID_PARAMETER;\r
2233 }\r
2234 \r
2235 //\r
2236 // Enable the maximum packet size (64bytes)\r
2237 // that can be used for full speed bandwidth reclamation\r
2238 // at the end of a frame.\r
2239 //\r
2240 EnableMaxPacketSize (HcDev);\r
2241\r
2242 Status = ClearStatusReg (HcDev->PciIo, StatusReg);\r
2243 if (EFI_ERROR (Status)) {\r
2244 return EFI_DEVICE_ERROR;\r
2245 }\r
2246 \r
2247 //\r
2248 // construct QH and TD data structures,\r
2249 // and link them together\r
2250 //\r
2251 if (EndPointAddress & 0x80) {\r
2252 TransferDirection = EfiUsbDataIn;\r
2253 } else {\r
2254 TransferDirection = EfiUsbDataOut;\r
2255 }\r
2256\r
2257 switch (TransferDirection) {\r
2258\r
2259 case EfiUsbDataIn:\r
2260 ShortPacketEnable = TRUE;\r
2261 PktID = INPUT_PACKET_ID;\r
2262 PtrDataSource = Data;\r
2263 DataLen = *DataLength;\r
2264\r
2265 //\r
2266 // BusMasterWrite means cpu read\r
2267 //\r
2268 Status = HcDev->PciIo->Map (\r
562d2849 2269 HcDev->PciIo,\r
2270 EfiPciIoOperationBusMasterWrite,\r
2271 PtrDataSource,\r
2272 &DataLen,\r
2273 &TempPtr,\r
2274 &Mapping\r
2275 );\r
878ddf1f 2276 if (EFI_ERROR (Status)) {\r
2277 return Status;\r
2278 }\r
2279\r
2280 Ptr = (UINT8 *) ((UINTN) TempPtr);\r
2281 break;\r
2282\r
2283 case EfiUsbDataOut:\r
2284 PktID = OUTPUT_PACKET_ID;\r
2285 PtrDataSource = Data;\r
2286 DataLen = *DataLength;\r
2287\r
2288 //\r
2289 // BusMasterRead means cpu write\r
2290 //\r
2291 Status = HcDev->PciIo->Map (\r
562d2849 2292 HcDev->PciIo,\r
2293 EfiPciIoOperationBusMasterRead,\r
2294 PtrDataSource,\r
2295 &DataLen,\r
2296 &TempPtr,\r
2297 &Mapping\r
2298 );\r
878ddf1f 2299 if (EFI_ERROR (Status)) {\r
2300 return Status;\r
2301 }\r
2302\r
2303 Ptr = (UINT8 *) ((UINTN) TempPtr);\r
2304 break;\r
2305\r
2306 default:\r
2307 return EFI_INVALID_PARAMETER;\r
2308 }\r
2309 \r
2310 //\r
2311 // create QH structure and init\r
2312 //\r
2313 Status = CreateQH (HcDev, &PtrQH);\r
2314 if (EFI_ERROR (Status)) {\r
2315 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2316 return Status;\r
2317 }\r
2318 \r
2319 //\r
2320 // i is used to calculate the total number of TDs.\r
2321 //\r
2322 Index = 0;\r
2323\r
2324 IsFirstTD = TRUE;\r
2325 while (DataLen > 0) {\r
2326 \r
2327 //\r
2328 // create TD structures and link together\r
2329 //\r
2330 \r
2331 PktSize = (UINT8) DataLen;\r
2332 if (DataLen > MaximumPacketLength) {\r
2333 PktSize = MaximumPacketLength;\r
2334 }\r
2335\r
2336 Status = GenDataTD (\r
562d2849 2337 HcDev,\r
2338 DeviceAddress,\r
2339 EndPointAddress,\r
2340 Ptr,\r
2341 PktSize,\r
2342 PktID,\r
2343 *DataToggle,\r
2344 FALSE,\r
2345 &PtrTD\r
2346 );\r
878ddf1f 2347\r
2348 if (EFI_ERROR (Status)) {\r
2349 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2350 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
2351 DeleteQueuedTDs (HcDev, PtrFirstTD);\r
2352 return Status;\r
2353 }\r
2354 \r
2355 //\r
2356 // Enable short packet detection.\r
2357 // (default action is disabling short packet detection)\r
2358 //\r
2359 if (ShortPacketEnable) {\r
2360 EnableorDisableTDShortPacket (PtrTD, TRUE);\r
2361 }\r
2362\r
2363 if (IsFirstTD) {\r
2364 PtrFirstTD = PtrTD;\r
2365 PtrFirstTD->ptrNextTD = NULL;\r
2366 IsFirstTD = FALSE;\r
2367 } else {\r
2368 //\r
2369 // Link two TDs in vertical depth\r
2370 //\r
2371 LinkTDToTD (PtrPreTD, PtrTD);\r
2372 }\r
2373\r
2374 Index++;\r
2375\r
2376 PtrPreTD = PtrTD;\r
2377\r
2378 *DataToggle ^= 1;\r
2379 Ptr += PktSize;\r
2380 DataLen -= PktSize;\r
2381 }\r
2382 \r
2383 //\r
2384 // link TD structures to QH structure\r
2385 //\r
2386 LinkTDToQH (PtrQH, PtrFirstTD);\r
2387\r
2388 //\r
2389 // calculate how many entries are linked to the specified bulk transfer QH-TDs\r
2390 // the below values are referred to the USB spec revision1.1.\r
2391 //\r
2392 switch (MaximumPacketLength) {\r
2393 case 8:\r
2394 LinkTimes = Index / 71 + 1;\r
2395 break;\r
2396\r
2397 case 16:\r
2398 LinkTimes = Index / 51 + 1;\r
2399 break;\r
2400\r
2401 case 32:\r
2402 LinkTimes = Index / 33 + 1;\r
2403 break;\r
2404\r
2405 case 64:\r
2406 LinkTimes = Index / 19 + 1;\r
2407 break;\r
2408 }\r
2409\r
2410 LinkTimes += 500;\r
2411\r
2412 //\r
2413 // put QH-TDs into Frame list\r
2414 //\r
2415 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
2416 SavedFrameListIndex = LoadFrameListIndex;\r
2417\r
2418 for (Index = 0; Index <= LinkTimes; Index++) {\r
2419 \r
2420 //\r
2421 // put the QH-TD directly or indirectly into the proper place\r
2422 // in the Frame List\r
2423 //\r
2424 LinkQHToFrameList (HcDev->FrameListEntry, LoadFrameListIndex, PtrQH);\r
2425\r
2426 LoadFrameListIndex += 1;\r
2427 LoadFrameListIndex &= 0x3FF;\r
2428 }\r
2429\r
2430 LoadFrameListIndex = SavedFrameListIndex;\r
2431\r
2432 //\r
2433 // Execute QH-TD and get result\r
2434 //\r
2435 //\r
2436 // detail status is put into the Result field in the pIRP\r
2437 // the Data Toggle value is also re-updated to the value\r
2438 // of the last successful TD\r
2439 //\r
2440 Status = ExecBulkorSyncInterruptTransfer (\r
562d2849 2441 HcDev,\r
2442 PtrFirstTD,\r
2443 LoadFrameListIndex,\r
2444 DataLength,\r
2445 DataToggle,\r
2446 TimeOut,\r
2447 TransferResult\r
2448 );\r
878ddf1f 2449\r
2450 //\r
2451 // Delete Bulk transfer QH-TD structure\r
2452 // and maitain the pointers in the Frame List\r
2453 // and other pointers in related QH structure\r
2454 //\r
2455 // TRUE means must search other framelistindex\r
2456 //\r
2457 for (Index = 0; Index <= LinkTimes; Index++) {\r
2458 DelLinkSingleQH (\r
2459 HcDev,\r
2460 PtrQH,\r
2461 LoadFrameListIndex,\r
2462 FALSE,\r
2463 FALSE\r
2464 );\r
2465 LoadFrameListIndex += 1;\r
2466 LoadFrameListIndex &= 0x3FF;\r
2467 }\r
2468\r
2469 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
2470\r
2471 DeleteQueuedTDs (HcDev, PtrFirstTD);\r
2472\r
2473 if (Mapping != NULL) {\r
2474 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2475 }\r
2476 \r
2477 //\r
2478 // if has errors that cause host controller halt,\r
2479 // then return EFI_DEVICE_ERROR directly.\r
2480 //\r
2481 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
2482\r
2483 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2484 *TransferResult |= EFI_USB_ERR_SYSTEM;\r
2485 return EFI_DEVICE_ERROR;\r
2486 }\r
2487\r
2488 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2489\r
2490 HcDev->PciIo->Flush (HcDev->PciIo);\r
2491\r
2492 return Status;\r
2493}\r
2494\r
2495EFI_STATUS\r
2496EFIAPI\r
2497UHCIAsyncInterruptTransfer (\r
2498 IN EFI_USB_HC_PROTOCOL * This,\r
2499 IN UINT8 DeviceAddress,\r
2500 IN UINT8 EndPointAddress,\r
2501 IN BOOLEAN IsSlowDevice,\r
562d2849 2502 IN UINT8 MaximumPacketLength,\r
878ddf1f 2503 IN BOOLEAN IsNewTransfer,\r
2504 IN OUT UINT8 *DataToggle,\r
2505 IN UINTN PollingInterval, OPTIONAL\r
2506 IN UINTN DataLength, OPTIONAL\r
2507 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, OPTIONAL\r
2508 IN VOID *Context OPTIONAL\r
2509 )\r
2510/*++\r
2511 \r
2512 Routine Description:\r
2513 Submits an asynchronous interrupt transfer to an \r
2514 interrupt endpoint of a USB device.\r
2515 \r
2516 Arguments:\r
2517 \r
2518 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
2519 \r
2520 DeviceAddress Represents the address of the target device on the USB,\r
2521 which is assigned during USB enumeration.\r
2522 \r
2523 EndPointAddress The combination of an endpoint number and an endpoint \r
2524 direction of the target USB device. Each endpoint address \r
2525 supports data transfer in one direction except the \r
2526 control endpoint (whose default endpoint address is 0). \r
2527 It is the caller's responsibility to make sure that \r
2528 the EndPointAddress represents an interrupt endpoint.\r
2529 \r
2530 IsSlowDevice Indicates whether the target device is slow device \r
2531 or full-speed device.\r
2532 \r
562d2849 2533 MaximumPacketLength Indicates the maximum packet size the target endpoint\r
878ddf1f 2534 is capable of sending or receiving.\r
2535 \r
2536 IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between\r
2537 the host and the target interrupt endpoint. \r
2538 If FALSE, the specified asynchronous interrupt pipe \r
2539 is canceled.\r
2540 \r
2541 DataToggle A pointer to the data toggle value. On input, it is valid \r
2542 when IsNewTransfer is TRUE, and it indicates the initial \r
2543 data toggle value the asynchronous interrupt transfer \r
2544 should adopt. \r
2545 On output, it is valid when IsNewTransfer is FALSE, \r
2546 and it is updated to indicate the data toggle value of \r
2547 the subsequent asynchronous interrupt transfer.\r
2548 \r
2549 PollingInterval Indicates the interval, in milliseconds, that the \r
2550 asynchronous interrupt transfer is polled. \r
2551 This parameter is required when IsNewTransfer is TRUE.\r
2552 \r
2553 DataLength Indicates the length of data to be received at the \r
2554 rate specified by PollingInterval from the target \r
2555 asynchronous interrupt endpoint. This parameter \r
2556 is only required when IsNewTransfer is TRUE.\r
2557 \r
2558 CallBackFunction The Callback function.This function is called at the \r
2559 rate specified by PollingInterval.This parameter is \r
2560 only required when IsNewTransfer is TRUE.\r
2561 \r
2562 Context The context that is passed to the CallBackFunction.\r
2563 This is an optional parameter and may be NULL.\r
2564 \r
2565 Returns:\r
2566 EFI_SUCCESS \r
2567 The asynchronous interrupt transfer request has been successfully \r
2568 submitted or canceled.\r
2569 EFI_INVALID_PARAMETER \r
2570 Some parameters are invalid.\r
2571 EFI_OUT_OF_RESOURCES \r
2572 The request could not be completed due to a lack of resources. \r
2573 EFI_DEVICE_ERROR\r
2574 Can't read register\r
2575--*/\r
2576{\r
2577 USB_HC_DEV *HcDev;\r
2578 UINT32 StatusReg;\r
2579 UINT32 FrameNumReg;\r
2580 UINTN DataLen;\r
2581 QH_STRUCT *ptrFirstQH;\r
2582 QH_STRUCT *PtrQH;\r
2583 QH_STRUCT *ptrPreQH;\r
2584 TD_STRUCT *PtrFirstTD;\r
2585 TD_STRUCT *PtrTD;\r
2586 TD_STRUCT *PtrPreTD;\r
2587 UINT16 LoadFrameListIndex;\r
2588 UINT16 Index;\r
2589 UINT8 PktID;\r
2590 UINT8 *Ptr;\r
2591 UINT8 *MappedPtr;\r
2592 BOOLEAN IsFirstTD;\r
2593 BOOLEAN IsFirstQH;\r
2594 EFI_STATUS Status;\r
2595 BOOLEAN ShortPacketEnable;\r
2596 UINT8 CurrentDataToggle;\r
2597 EFI_PHYSICAL_ADDRESS TempPtr;\r
2598 VOID *Mapping;\r
2599 UINT8 PktSize;\r
2600 QH_STRUCT *TempQH;\r
2601 EFI_TPL OldTpl;\r
2602\r
2603 HcDev = USB_HC_DEV_FROM_THIS (This);\r
2604 StatusReg = (UINT32) (USBSTS);\r
2605 FrameNumReg = (UINT32) (USBFRNUM);\r
2606 Mapping = NULL;\r
2607 ShortPacketEnable = FALSE;\r
2608\r
2609 PktID = INPUT_PACKET_ID;\r
2610 PtrTD = NULL;\r
2611 PtrFirstTD = NULL;\r
2612 PtrPreTD = NULL;\r
2613 Ptr = NULL;\r
2614 PtrQH = NULL;\r
2615 ptrPreQH = NULL;\r
2616 ptrFirstQH = NULL;\r
2617\r
2618 if ((EndPointAddress & 0x80) == 0) {\r
2619 return EFI_INVALID_PARAMETER;\r
2620 }\r
2621 \r
2622 //\r
2623 // delete Async interrupt transfer request\r
2624 //\r
2625 if (!IsNewTransfer) {\r
2626\r
2627 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);\r
2628\r
2629 Status = DeleteAsyncINTQHTDs (\r
562d2849 2630 HcDev,\r
2631 DeviceAddress,\r
2632 EndPointAddress,\r
2633 DataToggle\r
2634 );\r
878ddf1f 2635\r
2636 gBS->RestoreTPL (OldTpl);\r
2637\r
2638 return Status;\r
2639 }\r
2640 //\r
2641 // if has errors that cause host controller halt,\r
2642 // then return EFI_DEVICE_ERROR directly.\r
2643 //\r
2644 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
2645\r
2646 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2647 return EFI_DEVICE_ERROR;\r
2648 }\r
2649\r
2650 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2651\r
2652 //\r
2653 // submit Async interrupt transfer request\r
2654 //\r
2655 if (PollingInterval < 1 || PollingInterval > 255) {\r
2656 return EFI_INVALID_PARAMETER;\r
2657 }\r
2658\r
2659 if (DataLength == 0) {\r
2660 return EFI_INVALID_PARAMETER;\r
2661 }\r
2662\r
2663 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
2664 return EFI_INVALID_PARAMETER;\r
2665 }\r
2666\r
2667 ShortPacketEnable = TRUE;\r
2668 PktID = INPUT_PACKET_ID;\r
2669 DataLen = DataLength;\r
2670 Ptr = AllocatePool (DataLen);\r
2671 if (Ptr == NULL) {\r
2672 return EFI_OUT_OF_RESOURCES;\r
2673 }\r
2674\r
2675 //\r
2676 // BusMasterWrite means cpu read\r
2677 //\r
2678 Status = HcDev->PciIo->Map (\r
562d2849 2679 HcDev->PciIo,\r
2680 EfiPciIoOperationBusMasterWrite,\r
2681 Ptr,\r
2682 &DataLen,\r
2683 &TempPtr,\r
2684 &Mapping\r
2685 );\r
878ddf1f 2686 if (EFI_ERROR (Status)) {\r
2687 gBS->FreePool (Ptr);\r
2688 return Status;\r
2689 }\r
2690\r
2691 MappedPtr = (UINT8 *) ((UINTN) TempPtr);\r
2692\r
2693 CurrentDataToggle = *DataToggle;\r
2694\r
2695 IsFirstTD = TRUE;\r
2696\r
2697 while (DataLen > 0) {\r
2698 //\r
2699 // create TD structures and link together\r
2700 //\r
2701 \r
2702 PktSize = (UINT8) DataLen;\r
562d2849 2703 if (DataLen > MaximumPacketLength) {\r
2704 PktSize = MaximumPacketLength;\r
878ddf1f 2705 }\r
2706\r
2707 Status = GenDataTD (\r
562d2849 2708 HcDev,\r
2709 DeviceAddress,\r
2710 EndPointAddress,\r
2711 MappedPtr,\r
2712 PktSize,\r
2713 PktID,\r
2714 CurrentDataToggle,\r
2715 IsSlowDevice,\r
2716 &PtrTD\r
2717 );\r
2718 if (EFI_ERROR (Status)) {\r
2719 gBS->FreePool (Ptr);\r
878ddf1f 2720 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2721 DeleteQueuedTDs (HcDev, PtrFirstTD);\r
2722 return Status;\r
2723 }\r
2724 //\r
2725 // Enable short packet detection.\r
2726 //\r
2727 if (ShortPacketEnable) {\r
2728 EnableorDisableTDShortPacket (PtrTD, TRUE);\r
2729 }\r
2730\r
2731 if (IsFirstTD) {\r
2732 PtrFirstTD = PtrTD;\r
2733 PtrFirstTD->ptrNextTD = NULL;\r
2734 IsFirstTD = FALSE;\r
2735 } else {\r
2736 //\r
2737 // Link two TDs in vertical depth\r
2738 //\r
2739 LinkTDToTD (PtrPreTD, PtrTD);\r
2740 }\r
2741\r
2742 PtrPreTD = PtrTD;\r
2743\r
2744 CurrentDataToggle ^= 1;\r
2745 MappedPtr += PktSize;\r
2746 DataLen -= PktSize;\r
2747 }\r
2748 \r
2749 //\r
2750 // roll one value back\r
2751 //\r
2752 CurrentDataToggle ^= 1;\r
2753\r
2754 //\r
2755 // create a list of QH structures and init,\r
2756 // link TDs to all the QHs, and link all the QHs together using internal\r
2757 // defined pointer of the QH_STRUCT.\r
2758 //\r
2759 IsFirstQH = TRUE;\r
2760 ptrPreQH = NULL;\r
2761 for (Index = 0; Index < 1024;) {\r
2762\r
2763 Status = CreateQH (HcDev, &PtrQH);\r
2764 if (EFI_ERROR (Status)) {\r
2765 gBS->FreePool (Ptr);\r
2766 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2767 DeleteQueuedTDs (HcDev, PtrFirstTD);\r
2768 PtrQH = ptrFirstQH;\r
2769 while (PtrQH) {\r
2770 TempQH = PtrQH;\r
2771 PtrQH = TempQH->ptrNextIntQH;\r
2772 UhciFreePool (HcDev, (UINT8 *) TempQH, sizeof (QH_STRUCT));\r
2773 }\r
2774\r
2775 return Status;\r
2776 }\r
2777 \r
2778 //\r
2779 // link TD structures to QH structure\r
2780 //\r
2781 LinkTDToQH (PtrQH, PtrFirstTD);\r
2782\r
2783 if (IsFirstQH) {\r
2784 ptrFirstQH = PtrQH;\r
2785 ptrFirstQH->ptrNextIntQH = NULL;\r
2786 IsFirstQH = FALSE;\r
2787 } else {\r
2788 //\r
2789 // link neighbor QH structures together\r
2790 //\r
2791 ptrPreQH->ptrNextIntQH = PtrQH;\r
2792 }\r
2793\r
2794 ptrPreQH = PtrQH;\r
2795\r
2796 Index = (UINT16) (PollingInterval + Index);\r
2797 }\r
2798 //\r
2799 // last QH in QH list should set its next QH pointer to NULL.\r
2800 //\r
2801 PtrQH->ptrNextIntQH = NULL;\r
2802\r
2803 //\r
2804 // Save QH-TD structures in Interrupt transfer list,\r
2805 // for monitor interrupt transfer execution routine use.\r
2806 //\r
2807 InsertQHTDToINTList (\r
2808 HcDev,\r
2809 ptrFirstQH,\r
2810 PtrFirstTD,\r
2811 DeviceAddress,\r
2812 EndPointAddress,\r
2813 CurrentDataToggle,\r
2814 DataLength,\r
2815 PollingInterval,\r
2816 Mapping,\r
2817 Ptr,\r
2818 CallBackFunction,\r
2819 Context\r
2820 );\r
2821\r
2822 //\r
2823 // put QHs-TDs into Frame list\r
2824 //\r
2825 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
2826\r
2827 PtrQH = ptrFirstQH;\r
2828\r
2829 for (Index = LoadFrameListIndex; Index < (1024 + LoadFrameListIndex);) {\r
2830 \r
2831 //\r
2832 // put the QH-TD directly or indirectly into the proper place\r
2833 // in the Frame List\r
2834 //\r
2835 LinkQHToFrameList (HcDev->FrameListEntry, (UINT16) (Index & 0x3FF), PtrQH);\r
2836\r
2837 Index = (UINT16) (PollingInterval + Index);\r
2838\r
2839 PtrQH = PtrQH->ptrNextIntQH;\r
2840 }\r
2841\r
2842 HcDev->PciIo->Flush (HcDev->PciIo);\r
2843\r
2844 return EFI_SUCCESS;\r
2845}\r
2846\r
2847EFI_STATUS\r
2848EFIAPI\r
2849UHCISyncInterruptTransfer (\r
2850 IN EFI_USB_HC_PROTOCOL *This,\r
2851 IN UINT8 DeviceAddress,\r
2852 IN UINT8 EndPointAddress,\r
2853 IN BOOLEAN IsSlowDevice,\r
2854 IN UINT8 MaximumPacketLength,\r
2855 IN OUT VOID *Data,\r
2856 IN OUT UINTN *DataLength,\r
2857 IN OUT UINT8 *DataToggle,\r
2858 IN UINTN TimeOut,\r
2859 OUT UINT32 *TransferResult\r
2860 )\r
2861/*++\r
2862 \r
2863 Routine Description:\r
2864 Submits synchronous interrupt transfer to an interrupt endpoint \r
2865 of a USB device.\r
2866 \r
2867 Arguments:\r
2868 \r
2869 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
2870 \r
2871 DeviceAddress Represents the address of the target device on the USB, \r
2872 which is assigned during USB enumeration.\r
2873 \r
2874 EndPointAddress The combination of an endpoint number and an endpoint \r
2875 direction of the target USB device. Each endpoint \r
2876 address supports data transfer in one direction \r
2877 except the control endpoint (whose default \r
2878 endpoint address is 0). It is the caller's responsibility\r
2879 to make sure that the EndPointAddress represents \r
2880 an interrupt endpoint. \r
2881 \r
2882 IsSlowDevice Indicates whether the target device is slow device \r
2883 or full-speed device.\r
2884 \r
2885 MaximumPacketLength Indicates the maximum packet size the target endpoint \r
2886 is capable of sending or receiving.\r
2887 \r
2888 Data A pointer to the buffer of data that will be transmitted \r
2889 to USB device or received from USB device.\r
2890 \r
2891 DataLength On input, the size, in bytes, of the data buffer specified \r
2892 by Data. On output, the number of bytes transferred.\r
2893 \r
2894 DataToggle A pointer to the data toggle value. On input, it indicates\r
2895 the initial data toggle value the synchronous interrupt \r
2896 transfer should adopt; \r
2897 on output, it is updated to indicate the data toggle value \r
2898 of the subsequent synchronous interrupt transfer. \r
2899 \r
2900 TimeOut Indicates the maximum time, in microseconds, which the \r
2901 transfer is allowed to complete.\r
2902 \r
2903 TransferResult A pointer to the detailed result information from \r
2904 the synchronous interrupt transfer. \r
2905\r
2906 Returns:\r
2907 EFI_SUCCESS \r
2908 The synchronous interrupt transfer was completed successfully.\r
2909 EFI_OUT_OF_RESOURCES \r
2910 The synchronous interrupt transfer could not be submitted due \r
2911 to lack of resource.\r
2912 EFI_INVALID_PARAMETER \r
2913 Some parameters are invalid.\r
2914 EFI_TIMEOUT \r
2915 The synchronous interrupt transfer failed due to timeout.\r
2916 EFI_DEVICE_ERROR \r
2917 The synchronous interrupt transfer failed due to host controller \r
2918 or device error. Caller should check TranferResult for detailed \r
2919 error information. \r
2920--*/\r
2921{\r
2922 USB_HC_DEV *HcDev;\r
2923 UINT32 StatusReg;\r
2924 UINT32 FrameNumReg;\r
2925 UINTN DataLen;\r
2926 QH_STRUCT *PtrQH;\r
2927 TD_STRUCT *PtrFirstTD;\r
2928 TD_STRUCT *PtrTD;\r
2929 TD_STRUCT *PtrPreTD;\r
2930 UINT16 LoadFrameListIndex;\r
2931 UINT16 SavedFrameListIndex;\r
2932 UINT32 Index;\r
2933 UINT32 LinkTimes;\r
2934 UINT8 PktID;\r
2935 UINT8 *PtrDataSource;\r
2936 UINT8 *Ptr;\r
2937 BOOLEAN IsFirstTD;\r
2938 EFI_STATUS Status;\r
2939 BOOLEAN ShortPacketEnable;\r
2940 EFI_PHYSICAL_ADDRESS TempPtr;\r
2941 VOID *Mapping;\r
2942 UINT8 PktSize;\r
2943\r
2944 HcDev = USB_HC_DEV_FROM_THIS (This);\r
2945 StatusReg = (UINT32) (USBSTS);\r
2946 FrameNumReg = (UINT32) (USBFRNUM);\r
2947 ShortPacketEnable = FALSE;\r
2948 Mapping = NULL;\r
2949 PktID = INPUT_PACKET_ID;\r
2950 PtrTD = NULL;\r
2951 PtrFirstTD = NULL;\r
2952 PtrPreTD = NULL;\r
2953 DataLen = 0;\r
2954 Ptr = NULL;\r
2955 Index = 0;\r
2956 LinkTimes = 0;\r
2957\r
2958 //\r
2959 // Parameters Checking\r
2960 //\r
2961 \r
2962 if ((DataLength == NULL) ||\r
2963 (Data == NULL) ||\r
2964 (TransferResult == NULL)) {\r
2965 return EFI_INVALID_PARAMETER;\r
2966 }\r
2967 \r
2968 //\r
2969 // if has errors that cause host controller halt,\r
2970 // then return EFI_DEVICE_ERROR directly.\r
2971 //\r
2972 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
2973\r
2974 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2975 *TransferResult = EFI_USB_ERR_SYSTEM;\r
2976 return EFI_DEVICE_ERROR;\r
2977 }\r
2978\r
2979 if ((EndPointAddress & 0x80) == 0) {\r
2980 return EFI_INVALID_PARAMETER;\r
2981 }\r
2982\r
2983 if (*DataLength == 0) {\r
2984 return EFI_INVALID_PARAMETER;\r
2985 }\r
2986\r
2987 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
2988 return EFI_INVALID_PARAMETER;\r
2989 }\r
2990\r
2991 if (MaximumPacketLength > 64) {\r
2992 return EFI_INVALID_PARAMETER;\r
2993 }\r
2994\r
2995 if (IsSlowDevice && (MaximumPacketLength > 8)) {\r
2996 return EFI_INVALID_PARAMETER;\r
2997 }\r
2998\r
562d2849 2999 if (TransferResult == NULL) {\r
3000 return EFI_INVALID_PARAMETER;\r
3001 }\r
3002\r
878ddf1f 3003 ClearStatusReg (HcDev->PciIo, StatusReg);\r
3004\r
3005 //\r
3006 // submit Sync interrupt transfer request\r
3007 //\r
3008 ShortPacketEnable = TRUE;\r
3009 PktID = INPUT_PACKET_ID;\r
3010 DataLen = *DataLength;\r
3011 PtrDataSource = Data;\r
3012\r
3013 //\r
3014 // create QH structure and init\r
3015 //\r
3016 Status = CreateQH (HcDev, &PtrQH);\r
3017 if (EFI_ERROR (Status)) {\r
3018 return Status;\r
3019 }\r
3020 \r
3021 //\r
3022 // BusMasterWrite means cpu read\r
3023 //\r
3024 Status = HcDev->PciIo->Map (\r
3025 HcDev->PciIo,\r
3026 EfiPciIoOperationBusMasterWrite,\r
3027 PtrDataSource,\r
3028 &DataLen,\r
3029 &TempPtr,\r
3030 &Mapping\r
3031 );\r
3032 if (EFI_ERROR (Status)) {\r
3033 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
3034 return Status;\r
3035 }\r
3036\r
3037 Ptr = (UINT8 *) ((UINTN) TempPtr);\r
3038\r
3039 IsFirstTD = TRUE;\r
3040 while (DataLen > 0) {\r
3041 //\r
3042 // create TD structures and link together\r
3043 //\r
3044 PktSize = (UINT8) DataLen;\r
3045 if (DataLen > MaximumPacketLength) {\r
3046 PktSize = MaximumPacketLength;\r
3047 }\r
3048\r
3049 Status = GenDataTD (\r
3050 HcDev,\r
3051 DeviceAddress,\r
3052 EndPointAddress,\r
3053 Ptr,\r
3054 PktSize,\r
3055 PktID,\r
3056 *DataToggle,\r
3057 IsSlowDevice,\r
3058 &PtrTD\r
3059 );\r
3060 if (EFI_ERROR (Status)) {\r
3061 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
3062 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
3063 DeleteQueuedTDs (HcDev, PtrFirstTD);\r
3064 return Status;\r
3065 }\r
3066 //\r
3067 // Enable short packet detection.\r
3068 //\r
3069 if (ShortPacketEnable) {\r
3070 EnableorDisableTDShortPacket (PtrTD, TRUE);\r
3071 }\r
3072\r
3073 if (IsFirstTD) {\r
3074 PtrFirstTD = PtrTD;\r
3075 PtrFirstTD->ptrNextTD = NULL;\r
3076 IsFirstTD = FALSE;\r
3077 } else {\r
3078 //\r
3079 // Link two TDs in vertical depth\r
3080 //\r
3081 LinkTDToTD (PtrPreTD, PtrTD);\r
3082 }\r
3083\r
3084 Index++;\r
3085\r
3086 PtrPreTD = PtrTD;\r
3087\r
3088 *DataToggle ^= 1;\r
3089 Ptr += PktSize;\r
3090 DataLen -= PktSize;\r
3091 }\r
3092 \r
3093 //\r
3094 // link TD structures to QH structure\r
3095 //\r
3096 LinkTDToQH (PtrQH, PtrFirstTD);\r
3097\r
3098 switch (MaximumPacketLength) {\r
3099 case 8:\r
3100 LinkTimes = Index / 71 + 1;\r
3101 break;\r
3102\r
3103 case 16:\r
3104 LinkTimes = Index / 51 + 1;\r
3105 break;\r
3106\r
3107 case 32:\r
3108 LinkTimes = Index / 33 + 1;\r
3109 break;\r
3110\r
3111 case 64:\r
3112 LinkTimes = Index / 19 + 1;\r
3113 break;\r
3114 }\r
3115\r
3116 LinkTimes += 100;\r
3117\r
3118 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
3119 SavedFrameListIndex = LoadFrameListIndex;\r
3120\r
3121 for (Index = 0; Index < LinkTimes; Index++) {\r
3122 \r
3123 //\r
3124 // put the QH-TD directly or indirectly into the proper place\r
3125 // in the Frame List\r
3126 //\r
3127 LinkQHToFrameList (HcDev->FrameListEntry, LoadFrameListIndex, PtrQH);\r
3128\r
3129 LoadFrameListIndex += 1;\r
3130 LoadFrameListIndex &= 0x3FF;\r
3131 }\r
3132\r
3133 LoadFrameListIndex = SavedFrameListIndex;\r
3134 //\r
3135 // detail status is put into the Result field in the pIRP\r
3136 // the Data Toggle value is also re-updated to the value\r
3137 // of the last successful TD\r
3138 //\r
3139 Status = ExecBulkorSyncInterruptTransfer (\r
3140 HcDev,\r
3141 PtrFirstTD,\r
3142 LoadFrameListIndex,\r
3143 DataLength,\r
3144 DataToggle,\r
3145 TimeOut,\r
3146 TransferResult\r
3147 );\r
3148 //\r
3149 // Delete Sync Interrupt transfer QH-TD structure\r
3150 // and maintain the pointers in the Frame List\r
3151 // and other pointers in related QH structure\r
3152 //\r
3153 // TRUE means must search other framelistindex\r
3154 //\r
3155 for (Index = 0; Index <= LinkTimes; Index++) {\r
3156 DelLinkSingleQH (\r
3157 HcDev,\r
3158 PtrQH,\r
3159 LoadFrameListIndex,\r
3160 FALSE,\r
3161 FALSE\r
3162 );\r
3163 LoadFrameListIndex += 1;\r
3164 LoadFrameListIndex &= 0x3FF;\r
3165 }\r
3166\r
3167 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
3168\r
3169 DeleteQueuedTDs (HcDev, PtrFirstTD);\r
3170\r
3171 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
3172\r
3173 //\r
3174 // if has errors that cause host controller halt,\r
3175 // then return EFI_DEVICE_ERROR directly.\r
3176 //\r
3177 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
3178\r
3179 ClearStatusReg (HcDev->PciIo, StatusReg);\r
3180 *TransferResult |= EFI_USB_ERR_SYSTEM;\r
3181 return EFI_DEVICE_ERROR;\r
3182 }\r
3183\r
3184 ClearStatusReg (HcDev->PciIo, StatusReg);\r
3185\r
3186 HcDev->PciIo->Flush (HcDev->PciIo);\r
3187\r
3188 return Status;\r
3189}\r
3190\r
3191EFI_STATUS\r
3192EFIAPI\r
3193UHCIIsochronousTransfer (\r
3194 IN EFI_USB_HC_PROTOCOL *This,\r
3195 IN UINT8 DeviceAddress,\r
3196 IN UINT8 EndPointAddress,\r
3197 IN UINT8 MaximumPacketLength,\r
3198 IN OUT VOID *Data,\r
3199 IN UINTN DataLength,\r
3200 OUT UINT32 *TransferResult\r
3201 )\r
3202/*++\r
3203 \r
3204 Routine Description:\r
3205 Submits isochronous transfer to a target USB device.\r
3206 \r
3207 Arguments:\r
3208 \r
3209 This - A pointer to the EFI_USB_HC_PROTOCOL instance.\r
3210 DeviceAddress - Represents the address of the target device on the USB,\r
3211 which is assigned during USB enumeration.\r
3212 EndPointAddress - End point address\r
3213 MaximumPacketLength - Indicates the maximum packet size that the \r
3214 default control transfer endpoint is capable of \r
3215 sending or receiving.\r
3216 Data - A pointer to the buffer of data that will be transmitted \r
3217 to USB device or received from USB device.\r
3218 DataLength - Indicates the size, in bytes, of the data buffer \r
3219 specified by Data.\r
3220 TransferResult - A pointer to the detailed result information generated \r
3221 by this control transfer. \r
3222 Returns:\r
3223 EFI_UNSUPPORTED \r
3224\r
3225--*/\r
3226{\r
3227 return EFI_UNSUPPORTED;\r
3228}\r
3229\r
3230\r
3231EFI_STATUS\r
3232EFIAPI\r
3233UHCIAsyncIsochronousTransfer (\r
3234 IN EFI_USB_HC_PROTOCOL * This,\r
3235 IN UINT8 DeviceAddress,\r
3236 IN UINT8 EndPointAddress,\r
3237 IN UINT8 MaximumPacketLength,\r
3238 IN OUT VOID *Data,\r
3239 IN UINTN DataLength,\r
3240 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
3241 IN VOID *Context OPTIONAL\r
3242 )\r
3243/*++\r
3244 \r
3245 Routine Description:\r
3246 Submits Async isochronous transfer to a target USB device.\r
3247 \r
3248 Arguments:\r
3249 \r
3250 This - A pointer to the EFI_USB_HC_PROTOCOL instance.\r
3251 \r
3252 DeviceAddress - Represents the address of the target device on the USB,\r
3253 which is assigned during USB enumeration.\r
3254\r
3255 EndPointAddress - End point address\r
3256 \r
3257 MaximumPacketLength - Indicates the maximum packet size that the \r
3258 default control transfer endpoint is capable of \r
3259 sending or receiving.\r
3260 \r
3261 Data - A pointer to the buffer of data that will be transmitted \r
3262 to USB device or received from USB device.\r
3263 \r
3264 IsochronousCallBack - When the transfer complete, the call back function will be called\r
3265 \r
3266 Context - Pass to the call back function as parameter\r
3267 \r
3268 Returns:\r
3269 EFI_UNSUPPORTED \r
3270\r
3271--*/\r
3272{\r
3273 return EFI_UNSUPPORTED;\r
3274}\r
3275\r
562d2849 3276//\r
3277// UEFI 2.0 Protocol\r
3278//\r
3279EFI_STATUS\r
3280EFIAPI\r
3281UHCI2GetCapability(\r
3282 IN EFI_USB2_HC_PROTOCOL * This,\r
3283 OUT UINT8 *MaxSpeed,\r
3284 OUT UINT8 *PortNumber,\r
3285 OUT UINT8 *Is64BitCapable\r
3286 )\r
3287/*++\r
3288\r
3289 Routine Description:\r
3290 Retrieves capabilities of USB host controller according to UEFI 2.0 spec.\r
3291\r
3292 Arguments:\r
3293 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
3294 \r
3295 MaxSpeed - A pointer to the max speed USB host controller supports.\r
3296 \r
3297 PortNumber - A pointer to the number of root hub ports.\r
3298 \r
3299 Is64BitCapable - A pointer to an integer to show whether USB host controller\r
3300 supports 64-bit memory addressing.\r
3301 Returns:\r
3302 EFI_SUCCESS \r
3303 The host controller capabilities were retrieved successfully.\r
3304 EFI_INVALID_PARAMETER \r
3305 MaxSpeed or PortNumber or Is64BitCapable is NULL.\r
3306 EFI_DEVICE_ERROR \r
3307 An error was encountered while attempting to retrieve the capabilities.\r
3308 \r
3309--*/ \r
3310{\r
3311 USB_HC_DEV *HcDev;\r
3312\r
3313 HcDev = USB2_HC_DEV_FROM_THIS (This);\r
3314 \r
3315 if ((NULL == MaxSpeed) \r
3316 ||(NULL == PortNumber)\r
3317 || (NULL == Is64BitCapable))\r
3318 {\r
3319 return EFI_INVALID_PARAMETER;\r
3320 }\r
3321 \r
3322 *MaxSpeed = EFI_USB_SPEED_FULL;\r
3323 *Is64BitCapable = (UINT8)FALSE;\r
3324 return UHCIGetRootHubPortNumber(&HcDev->UsbHc, PortNumber);\r
3325}\r
3326\r
3327EFI_STATUS\r
3328EFIAPI\r
3329UHCI2Reset (\r
3330 IN EFI_USB2_HC_PROTOCOL * This,\r
3331 IN UINT16 Attributes\r
3332 )\r
3333/*++\r
3334\r
3335 Routine Description:\r
3336 Provides software reset for the USB host controller according to UEFI 2.0 spec.\r
3337\r
3338 Arguments:\r
3339 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
3340 \r
3341 Attributes - A bit mask of the reset operation to perform. \r
3342 See below for a list of the supported bit mask values.\r
3343 \r
3344 #define EFI_USB_HC_RESET_GLOBAL 0x0001\r
3345 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002\r
3346 #define EFI_USB_HC_RESET_GLOBAL _WITH_DEBUG 0x0004\r
3347 #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008\r
3348\r
3349 EFI_USB_HC_RESET_GLOBAL \r
3350 If this bit is set, a global reset signal will be sent to the USB bus.\r
3351 This resets all of the USB bus logic, including the USB host \r
3352 controller hardware and all the devices attached on the USB bus.\r
3353 EFI_USB_HC_RESET_HOST_CONTROLLER \r
3354 If this bit is set, the USB host controller hardware will be reset. \r
3355 No reset signal will be sent to the USB bus.\r
3356 \r
3357 Returns:\r
3358 EFI_SUCCESS \r
3359 The reset operation succeeded.\r
3360 EFI_INVALID_PARAMETER \r
3361 Attributes is not valid.\r
3362 EFI_UNSUPPORTED\r
3363 The type of reset specified by Attributes is not currently supported by the host controller hardware.\r
3364 EFI_ACCESS_DENIED\r
3365 Reset operation is rejected due to the debug port being configured and active.\r
3366 EFI_DEVICE_ERROR \r
3367 An error was encountered while attempting to perform \r
3368 the reset operation.\r
3369--*/\r
3370{\r
3371 USB_HC_DEV *HcDev;\r
3372\r
3373 HcDev = USB2_HC_DEV_FROM_THIS (This);\r
3374 \r
3375 if (Attributes==EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG || Attributes==EFI_USB_HC_RESET_HOST_WITH_DEBUG)\r
3376 return EFI_UNSUPPORTED;\r
3377 \r
3378 return UHCIReset(\r
3379 &HcDev->UsbHc, \r
3380 Attributes\r
3381 );\r
3382}\r
3383\r
3384EFI_STATUS\r
3385EFIAPI\r
3386UHCI2GetState (\r
3387 IN EFI_USB2_HC_PROTOCOL * This,\r
3388 OUT EFI_USB_HC_STATE * State\r
3389 )\r
3390/*++\r
3391 \r
3392 Routine Description:\r
3393 Retrieves current state of the USB host controller according to UEFI 2.0 spec.\r
3394 \r
3395 Arguments:\r
3396 \r
3397 This - A pointer to the EFI_USB_HC_PROTOCOL instance.\r
3398 \r
3399 State - A pointer to the EFI_USB_HC_STATE data structure that \r
3400 indicates current state of the USB host controller. \r
3401 Type EFI_USB_HC_STATE is defined below.\r
3402 \r
3403 typedef enum {\r
3404 EfiUsbHcStateHalt,\r
3405 EfiUsbHcStateOperational,\r
3406 EfiUsbHcStateSuspend,\r
3407 EfiUsbHcStateMaximum\r
3408 } EFI_USB_HC_STATE;\r
3409 \r
3410 Returns:\r
3411 EFI_SUCCESS \r
3412 The state information of the host controller was returned in State.\r
3413 EFI_INVALID_PARAMETER \r
3414 State is NULL.\r
3415 EFI_DEVICE_ERROR \r
3416 An error was encountered while attempting to retrieve the \r
3417 host controller's current state. \r
3418--*/ \r
3419{\r
3420 USB_HC_DEV *HcDev;\r
3421\r
3422 HcDev = USB2_HC_DEV_FROM_THIS (This);\r
3423 return UHCIGetState(\r
3424 &HcDev->UsbHc, \r
3425 State\r
3426 );\r
3427}\r
3428\r
3429EFI_STATUS\r
3430EFIAPI\r
3431UHCI2SetState (\r
3432 IN EFI_USB2_HC_PROTOCOL * This,\r
3433 IN EFI_USB_HC_STATE State\r
3434 )\r
3435/*++\r
3436 \r
3437 Routine Description:\r
3438 Sets the USB host controller to a specific state according to UEFI 2.0 spec.\r
3439 \r
3440 Arguments:\r
3441 \r
3442 This - A pointer to the EFI_USB_HC_PROTOCOL instance.\r
3443\r
3444 State - Indicates the state of the host controller that will be set.\r
3445 \r
3446 Returns:\r
3447 EFI_SUCCESS \r
3448 The USB host controller was successfully placed in the state \r
3449 specified by State.\r
3450 EFI_INVALID_PARAMETER \r
3451 State is invalid.\r
3452 EFI_DEVICE_ERROR \r
3453 Failed to set the state specified by State due to device error. \r
3454--*/\r
3455{\r
3456 USB_HC_DEV *HcDev;\r
3457\r
3458 HcDev = USB2_HC_DEV_FROM_THIS (This);\r
3459 return UHCISetState(\r
3460 &HcDev->UsbHc, \r
3461 State\r
3462 );\r
3463}\r
3464\r
3465EFI_STATUS\r
3466EFIAPI\r
3467UHCI2ControlTransfer (\r
3468 IN EFI_USB2_HC_PROTOCOL * This,\r
3469 IN UINT8 DeviceAddress,\r
3470 IN UINT8 DeviceSpeed,\r
3471 IN UINTN MaximumPacketLength,\r
3472 IN EFI_USB_DEVICE_REQUEST * Request,\r
3473 IN EFI_USB_DATA_DIRECTION TransferDirection,\r
3474 IN OUT VOID *Data,\r
3475 IN OUT UINTN *DataLength,\r
3476 IN UINTN TimeOut,\r
3477 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
3478 OUT UINT32 *TransferResult\r
3479 )\r
3480/*++\r
3481 \r
3482 Routine Description:\r
3483 Submits control transfer to a target USB device accroding to UEFI 2.0 spec..\r
3484 \r
3485 Arguments:\r
3486 \r
3487 This - A pointer to the EFI_USB_HC_PROTOCOL instance.\r
3488\r
3489 DeviceAddress -Represents the address of the target device on the USB,\r
3490 which is assigned during USB enumeration.\r
3491\r
3492 DeviceSpeed - Indicates transfer speed of device.\r
3493 \r
3494 MaximumPacketLength - Indicates the maximum packet size that the \r
3495 default control transfer endpoint is capable of \r
3496 sending or receiving.\r
3497 \r
3498 Request - A pointer to the USB device request that will be sent \r
3499 to the USB device. \r
3500 \r
3501 TransferDirection - Specifies the data direction for the transfer.\r
3502 There are three values available, DataIn, DataOut \r
3503 and NoData.\r
3504 \r
3505 Data -A pointer to the buffer of data that will be transmitted \r
3506 to USB device or received from USB device.\r
3507 \r
3508 DataLength - Indicates the size, in bytes, of the data buffer \r
3509 specified by Data.\r
3510 \r
3511 TimeOut - Indicates the maximum time, in microseconds, \r
3512 which the transfer is allowed to complete.\r
3513 \r
3514 TransferResult - A pointer to the detailed result information generated \r
3515 by this control transfer.\r
3516 \r
3517 Returns:\r
3518 EFI_SUCCESS \r
3519 The control transfer was completed successfully.\r
3520 EFI_OUT_OF_RESOURCES \r
3521 The control transfer could not be completed due to a lack of resources.\r
3522 EFI_INVALID_PARAMETER \r
3523 Some parameters are invalid.\r
3524 EFI_TIMEOUT \r
3525 The control transfer failed due to timeout.\r
3526 EFI_DEVICE_ERROR \r
3527 The control transfer failed due to host controller or device error. \r
3528 Caller should check TranferResult for detailed error information.\r
3529\r
3530--*/\r
3531{\r
3532 USB_HC_DEV *HcDev;\r
1cc8ee78 3533 BOOLEAN IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
562d2849 3534\r
3535 HcDev = USB2_HC_DEV_FROM_THIS (This);\r
3536 \r
3537 return UHCIControlTransfer(\r
3538 &HcDev->UsbHc, \r
3539 DeviceAddress, \r
3540 IsSlowDevice, \r
3541 (UINT8) MaximumPacketLength, \r
3542 Request, \r
3543 TransferDirection, \r
3544 Data, \r
3545 DataLength,\r
3546 TimeOut,\r
3547 TransferResult\r
3548 ); \r
3549}\r
3550\r
3551EFI_STATUS\r
3552EFIAPI\r
3553UHCI2BulkTransfer (\r
3554 IN EFI_USB2_HC_PROTOCOL * This,\r
3555 IN UINT8 DeviceAddress,\r
3556 IN UINT8 EndPointAddress,\r
3557 IN UINT8 DeviceSpeed,\r
3558 IN UINTN MaximumPacketLength,\r
3559 IN UINT8 DataBuffersNumber,\r
3560 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
3561 IN OUT UINTN *DataLength,\r
3562 IN OUT UINT8 *DataToggle,\r
3563 IN UINTN TimeOut,\r
3564 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
3565 OUT UINT32 *TransferResult\r
3566 ) \r
3567/*++\r
3568 \r
3569 Routine Description:\r
3570 Submits bulk transfer to a bulk endpoint of a USB device according to UEFI 2.0 spec.\r
3571 \r
3572 Arguments:\r
3573 \r
3574 This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
3575 \r
3576 DeviceAddress Represents the address of the target device on the USB,\r
3577 which is assigned during USB enumeration.\r
3578 \r
3579 EndPointAddress The combination of an endpoint number and an \r
3580 endpoint direction of the target USB device. \r
3581 Each endpoint address supports data transfer in \r
3582 one direction except the control endpoint \r
3583 (whose default endpoint address is 0). \r
3584 It is the caller's responsibility to make sure that \r
3585 the EndPointAddress represents a bulk endpoint. \r
3586 \r
3587 DeviceSpeed Indicates device speed. The supported values are EFI_USB_SPEED_FULL\r
3588 and EFI_USB_SPEED_HIGH.\r
3589 \r
3590 MaximumPacketLength Indicates the maximum packet size the target endpoint\r
3591 is capable of sending or receiving.\r
3592 \r
3593 DataBuffersNumber Number of data buffers prepared for the transfer.\r
3594 \r
3595 Data Array of pointers to the buffers of data that will be transmitted \r
3596 to USB device or received from USB device.\r
3597 \r
3598 DataLength When input, indicates the size, in bytes, of the data buffer\r
3599 specified by Data. When output, indicates the actually \r
3600 transferred data size.\r
3601 \r
3602 DataToggle A pointer to the data toggle value. On input, it indicates \r
3603 the initial data toggle value the bulk transfer should adopt;\r
3604 on output, it is updated to indicate the data toggle value \r
3605 of the subsequent bulk transfer. \r
3606 \r
3607 Translator A pointr to the transaction translator data.\r
3608 \r
3609 TimeOut Indicates the maximum time, in microseconds, which the \r
3610 transfer is allowed to complete.\r
3611 \r
3612 TransferResult A pointer to the detailed result information of the \r
3613 bulk transfer.\r
3614\r
3615 Returns:\r
3616 EFI_SUCCESS \r
3617 The bulk transfer was completed successfully.\r
3618 \r
3619 EFI_OUT_OF_RESOURCES \r
3620 The bulk transfer could not be submitted due to lack of resource.\r
3621 \r
3622 EFI_INVALID_PARAMETER \r
3623 Some parameters are invalid.\r
3624 \r
3625 EFI_TIMEOUT \r
3626 The bulk transfer failed due to timeout.\r
3627 \r
3628 EFI_DEVICE_ERROR \r
3629 The bulk transfer failed due to host controller or device error.\r
3630 Caller should check TranferResult for detailed error information.\r
3631\r
3632--*/ \r
3633{\r
3634 USB_HC_DEV *HcDev;\r
3635\r
3636 HcDev = USB2_HC_DEV_FROM_THIS (This);\r
3637 \r
3638 if( Data == NULL || DeviceSpeed==EFI_USB_SPEED_LOW)\r
3639 return EFI_INVALID_PARAMETER;\r
3640 /* For full-speed bulk transfers only the data pointed by Data[0] shall be used */\r
3641\r
3642 return UHCIBulkTransfer (\r
3643 &HcDev->UsbHc, \r
3644 DeviceAddress, \r
3645 EndPointAddress, \r
3646 (UINT8) MaximumPacketLength, \r
3647 *Data, \r
3648 DataLength, \r
3649 DataToggle, \r
3650 TimeOut, \r
3651 TransferResult\r
3652 );\r
3653}\r
3654\r
3655EFI_STATUS\r
3656EFIAPI\r
3657UHCI2AsyncInterruptTransfer (\r
3658 IN EFI_USB2_HC_PROTOCOL * This,\r
3659 IN UINT8 DeviceAddress,\r
3660 IN UINT8 EndPointAddress,\r
3661 IN UINT8 DeviceSpeed,\r
3662 IN UINTN MaximumPacketLength,\r
3663 IN BOOLEAN IsNewTransfer,\r
3664 IN OUT UINT8 *DataToggle,\r
3665 IN UINTN PollingInterval,\r
3666 IN UINTN DataLength,\r
3667 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
3668 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,\r
3669 IN VOID *Context\r
3670 )\r
3671/*++\r
3672 \r
3673 Routine Description:\r
3674 Submits an asynchronous interrupt transfer to an \r
3675 interrupt endpoint of a USB device according to UEFI 2.0 spec.\r
3676 \r
3677 Arguments:\r
3678 \r
3679 This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
3680 \r
3681 DeviceAddress Represents the address of the target device on the USB,\r
3682 which is assigned during USB enumeration.\r
3683 \r
3684 EndPointAddress The combination of an endpoint number and an endpoint \r
3685 direction of the target USB device. Each endpoint address \r
3686 supports data transfer in one direction except the \r
3687 control endpoint (whose default endpoint address is 0). \r
3688 It is the caller's responsibility to make sure that \r
3689 the EndPointAddress represents an interrupt endpoint.\r
3690 \r
3691 DeviceSpeed Indicates device speed.\r
3692 \r
3693 MaximumPacketLength Indicates the maximum packet size the target endpoint\r
3694 is capable of sending or receiving.\r
3695 \r
3696 IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between\r
3697 the host and the target interrupt endpoint. \r
3698 If FALSE, the specified asynchronous interrupt pipe \r
3699 is canceled.\r
3700 \r
3701 DataToggle A pointer to the data toggle value. On input, it is valid \r
3702 when IsNewTransfer is TRUE, and it indicates the initial \r
3703 data toggle value the asynchronous interrupt transfer \r
3704 should adopt. \r
3705 On output, it is valid when IsNewTransfer is FALSE, \r
3706 and it is updated to indicate the data toggle value of \r
3707 the subsequent asynchronous interrupt transfer.\r
3708 \r
3709 PollingInterval Indicates the interval, in milliseconds, that the \r
3710 asynchronous interrupt transfer is polled. \r
3711 This parameter is required when IsNewTransfer is TRUE.\r
3712 \r
3713 DataLength Indicates the length of data to be received at the \r
3714 rate specified by PollingInterval from the target \r
3715 asynchronous interrupt endpoint. This parameter \r
3716 is only required when IsNewTransfer is TRUE.\r
3717 \r
3718 Translator A pointr to the transaction translator data.\r
3719 \r
3720 CallBackFunction The Callback function.This function is called at the \r
3721 rate specified by PollingInterval.This parameter is \r
3722 only required when IsNewTransfer is TRUE.\r
3723 \r
3724 Context The context that is passed to the CallBackFunction.\r
3725 This is an optional parameter and may be NULL.\r
3726 \r
3727 Returns:\r
3728 \r
3729 EFI_SUCCESS \r
3730 The asynchronous interrupt transfer request has been successfully \r
3731 submitted or canceled.\r
3732 \r
3733 EFI_INVALID_PARAMETER \r
3734 Some parameters are invalid.\r
3735 \r
3736 EFI_OUT_OF_RESOURCES \r
3737 The request could not be completed due to a lack of resources. \r
3738 \r
3739 EFI_DEVICE_ERROR\r
3740 Can't read register\r
3741--*/ \r
3742{\r
3743 USB_HC_DEV *HcDev;\r
1cc8ee78 3744 BOOLEAN IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
562d2849 3745 \r
3746 HcDev = USB2_HC_DEV_FROM_THIS (This);\r
3747 return UHCIAsyncInterruptTransfer(\r
3748 &HcDev->UsbHc, \r
3749 DeviceAddress, \r
3750 EndPointAddress, \r
3751 IsSlowDevice, \r
3752 (UINT8) MaximumPacketLength, \r
3753 IsNewTransfer, \r
3754 DataToggle, \r
3755 PollingInterval,\r
3756 DataLength, \r
3757 CallBackFunction,\r
3758 Context\r
3759 );\r
3760}\r
3761\r
3762EFI_STATUS\r
3763EFIAPI\r
3764UHCI2SyncInterruptTransfer (\r
3765 IN EFI_USB2_HC_PROTOCOL * This,\r
3766 IN UINT8 DeviceAddress,\r
3767 IN UINT8 EndPointAddress,\r
3768 IN UINT8 DeviceSpeed,\r
3769 IN UINTN MaximumPacketLength,\r
3770 IN OUT VOID *Data,\r
3771 IN OUT UINTN *DataLength,\r
3772 IN OUT UINT8 *DataToggle,\r
3773 IN UINTN TimeOut,\r
3774 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
3775 OUT UINT32 *TransferResult\r
3776 )\r
3777/*++\r
3778 \r
3779 Routine Description:\r
3780 Submits synchronous interrupt transfer to an interrupt endpoint \r
3781 of a USB device according to UEFI 2.0 spec.\r
3782 \r
3783 Arguments:\r
3784 \r
3785 This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
3786 \r
3787 DeviceAddress Represents the address of the target device on the USB, \r
3788 which is assigned during USB enumeration.\r
3789 \r
3790 EndPointAddress The combination of an endpoint number and an endpoint \r
3791 direction of the target USB device. Each endpoint \r
3792 address supports data transfer in one direction \r
3793 except the control endpoint (whose default \r
3794 endpoint address is 0). It is the caller's responsibility\r
3795 to make sure that the EndPointAddress represents \r
3796 an interrupt endpoint. \r
3797 \r
3798 DeviceSpeed Indicates device speed.\r
3799 \r
3800 MaximumPacketLength Indicates the maximum packet size the target endpoint \r
3801 is capable of sending or receiving.\r
3802 \r
3803 Data A pointer to the buffer of data that will be transmitted \r
3804 to USB device or received from USB device.\r
3805 \r
3806 DataLength On input, the size, in bytes, of the data buffer specified \r
3807 by Data. On output, the number of bytes transferred.\r
3808 \r
3809 DataToggle A pointer to the data toggle value. On input, it indicates\r
3810 the initial data toggle value the synchronous interrupt \r
3811 transfer should adopt; \r
3812 on output, it is updated to indicate the data toggle value \r
3813 of the subsequent synchronous interrupt transfer. \r
3814 \r
3815 TimeOut Indicates the maximum time, in microseconds, which the \r
3816 transfer is allowed to complete.\r
3817 Translator A pointr to the transaction translator data.\r
3818 TransferResult A pointer to the detailed result information from \r
3819 the synchronous interrupt transfer. \r
3820\r
3821 Returns:\r
3822 EFI_SUCCESS \r
3823 The synchronous interrupt transfer was completed successfully.\r
3824 EFI_OUT_OF_RESOURCES \r
3825 The synchronous interrupt transfer could not be submitted due \r
3826 to lack of resource.\r
3827 EFI_INVALID_PARAMETER \r
3828 Some parameters are invalid.\r
3829 EFI_TIMEOUT \r
3830 The synchronous interrupt transfer failed due to timeout.\r
3831 EFI_DEVICE_ERROR \r
3832 The synchronous interrupt transfer failed due to host controller \r
3833 or device error. Caller should check TranferResult for detailed \r
3834 error information. \r
3835--*/ \r
3836{\r
3837 USB_HC_DEV *HcDev;\r
3838 BOOLEAN IsSlowDevice;\r
3839 \r
3840 if(DeviceSpeed==EFI_USB_SPEED_HIGH)\r
3841 return EFI_INVALID_PARAMETER;\r
3842 \r
1cc8ee78 3843 IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE); \r
562d2849 3844 HcDev = USB2_HC_DEV_FROM_THIS (This);\r
3845 \r
3846 return UHCISyncInterruptTransfer(\r
3847 &HcDev->UsbHc, \r
3848 DeviceAddress, \r
3849 EndPointAddress, \r
3850 IsSlowDevice, \r
3851 (UINT8) MaximumPacketLength, \r
3852 Data, \r
3853 DataLength, \r
3854 DataToggle,\r
3855 TimeOut,\r
3856 TransferResult\r
3857 );\r
3858}\r
3859\r
3860EFI_STATUS\r
3861EFIAPI\r
3862UHCI2IsochronousTransfer (\r
3863 IN EFI_USB2_HC_PROTOCOL * This,\r
3864 IN UINT8 DeviceAddress,\r
3865 IN UINT8 EndPointAddress,\r
3866 IN UINT8 DeviceSpeed,\r
3867 IN UINTN MaximumPacketLength,\r
3868 IN UINT8 DataBuffersNumber,\r
3869 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
3870 IN UINTN DataLength,\r
3871 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
3872 OUT UINT32 *TransferResult\r
3873 )\r
3874/*++\r
3875 \r
3876 Routine Description:\r
3877 \r
3878 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
3879 \r
3880 Arguments:\r
3881 \r
3882 This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
3883 \r
3884 DeviceAddress Represents the address of the target device on the USB,\r
3885 which is assigned during USB enumeration.\r
3886 \r
3887 EndPointAddress End point address\r
3888 \r
3889 DeviceSpeed Indicates device speed.\r
3890 \r
3891 MaximumPacketLength Indicates the maximum packet size that the \r
3892 default control transfer endpoint is capable of \r
3893 sending or receiving.\r
3894 \r
3895 DataBuffersNumber Number of data buffers prepared for the transfer.\r
3896 \r
3897 Data Array of pointers to the buffers of data that will be \r
3898 transmitted to USB device or received from USB device.\r
3899 \r
3900 DataLength Indicates the size, in bytes, of the data buffer \r
3901 specified by Data.\r
3902 \r
3903 Translator A pointr to the transaction translator data.\r
3904 \r
3905 TransferResult A pointer to the detailed result information generated \r
3906 by this control transfer. \r
3907 Returns:\r
3908 \r
3909 EFI_UNSUPPORTED \r
3910\r
3911--*/ \r
3912{\r
3913 return EFI_UNSUPPORTED;\r
3914}\r
3915\r
3916EFI_STATUS\r
3917EFIAPI\r
3918UHCI2AsyncIsochronousTransfer (\r
3919 IN EFI_USB2_HC_PROTOCOL * This,\r
3920 IN UINT8 DeviceAddress,\r
3921 IN UINT8 EndPointAddress,\r
3922 IN UINT8 DeviceSpeed,\r
3923 IN UINTN MaximumPacketLength,\r
3924 IN UINT8 DataBuffersNumber,\r
3925 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
3926 IN UINTN DataLength,\r
3927 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
3928 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
3929 IN VOID *Context\r
3930 )\r
3931/*++\r
3932 \r
3933 Routine Description:\r
3934 \r
3935 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
3936 \r
3937 Arguments:\r
3938 \r
3939 This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
3940 \r
3941 DeviceAddress Represents the address of the target device on the USB,\r
3942 which is assigned during USB enumeration.\r
3943\r
3944 EndPointAddress End point address\r
3945 \r
3946 DeviceSpeed Indicates device speed.\r
3947 \r
3948 MaximumPacketLength Indicates the maximum packet size that the \r
3949 default control transfer endpoint is capable of \r
3950 sending or receiving.\r
3951 \r
3952 DataBuffersNumber Number of data buffers prepared for the transfer.\r
3953 \r
3954 Data Array of pointers to the buffers of data that will be transmitted \r
3955 to USB device or received from USB device.\r
3956 \r
3957 Translator A pointr to the transaction translator data.\r
3958 \r
3959 IsochronousCallBack When the transfer complete, the call back function will be called\r
3960 \r
3961 Context Pass to the call back function as parameter\r
3962 \r
3963 Returns:\r
3964 \r
3965 EFI_UNSUPPORTED \r
3966\r
3967--*/ \r
3968{\r
3969 return EFI_UNSUPPORTED;\r
3970}\r
3971\r
3972EFI_STATUS\r
3973EFIAPI\r
3974UHCI2GetRootHubPortStatus (\r
3975 IN EFI_USB2_HC_PROTOCOL * This,\r
3976 IN UINT8 PortNumber,\r
3977 OUT EFI_USB_PORT_STATUS * PortStatus\r
3978 )\r
3979/*++\r
3980 \r
3981 Routine Description:\r
3982 Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.\r
3983 \r
3984 Arguments:\r
3985 \r
3986 This A pointer to the EFI_USB2_HC_PROTOCOL.\r
3987 \r
3988 PortNumber Specifies the root hub port from which the status \r
3989 is to be retrieved. This value is zero-based. For example, \r
3990 if a root hub has two ports, then the first port is numbered 0,\r
3991 and the second port is numbered 1.\r
3992 \r
3993 PortStatus A pointer to the current port status bits and \r
3994 port status change bits. \r
3995 \r
3996 Returns:\r
3997 EFI_SUCCESS \r
3998 The status of the USB root hub port specified by PortNumber \r
3999 was returned in PortStatus.\r
4000 EFI_INVALID_PARAMETER \r
4001 PortNumber is invalid. \r
4002 EFI_DEVICE_ERROR - Can't read register \r
4003--*/ \r
4004{\r
4005 USB_HC_DEV *HcDev;\r
4006\r
4007 HcDev = USB2_HC_DEV_FROM_THIS (This);\r
4008 \r
4009 return UHCIGetRootHubPortStatus(\r
4010 &HcDev->UsbHc, \r
4011 PortNumber, \r
4012 PortStatus\r
4013 );\r
4014}\r
4015\r
4016EFI_STATUS\r
4017EFIAPI\r
4018UHCI2SetRootHubPortFeature (\r
4019 IN EFI_USB2_HC_PROTOCOL * This,\r
4020 IN UINT8 PortNumber,\r
4021 IN EFI_USB_PORT_FEATURE PortFeature\r
4022 )\r
4023/*++\r
4024 \r
4025 Routine Description:\r
4026 Sets a feature for the specified root hub port according to UEFI 2.0 spec.\r
4027 \r
4028 Arguments:\r
4029 \r
4030 This A pointer to the EFI_USB2_HC_PROTOCOL.\r
4031 \r
4032 PortNumber Specifies the root hub port whose feature \r
4033 is requested to be set.\r
4034 \r
4035 PortFeature Indicates the feature selector associated \r
4036 with the feature set request. \r
4037 \r
4038 Returns:\r
4039 EFI_SUCCESS \r
4040 The feature specified by PortFeature was set for the \r
4041 USB root hub port specified by PortNumber.\r
4042 EFI_INVALID_PARAMETER \r
4043 PortNumber is invalid or PortFeature is invalid.\r
4044 EFI_DEVICE_ERROR\r
4045 Can't read register\r
4046--*/ \r
4047{\r
4048 USB_HC_DEV *HcDev;\r
4049\r
4050 HcDev = USB2_HC_DEV_FROM_THIS (This);\r
4051 return UHCISetRootHubPortFeature(\r
4052 &HcDev->UsbHc, \r
4053 PortNumber, \r
4054 PortFeature\r
4055 );\r
4056}\r
4057\r
4058EFI_STATUS\r
4059EFIAPI\r
4060UHCI2ClearRootHubPortFeature (\r
4061 IN EFI_USB2_HC_PROTOCOL * This,\r
4062 IN UINT8 PortNumber,\r
4063 IN EFI_USB_PORT_FEATURE PortFeature\r
4064 )\r
4065/*++\r
4066 \r
4067 Routine Description:\r
4068 Clears a feature for the specified root hub port according to Uefi 2.0 spec.\r
4069 \r
4070 Arguments:\r
4071 \r
4072 This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
4073 \r
4074 PortNumber Specifies the root hub port whose feature \r
4075 is requested to be cleared.\r
4076 \r
4077 PortFeature Indicates the feature selector associated with the \r
4078 feature clear request.\r
4079 \r
4080 Returns:\r
4081 EFI_SUCCESS \r
4082 The feature specified by PortFeature was cleared for the \r
4083 USB root hub port specified by PortNumber.\r
4084 EFI_INVALID_PARAMETER \r
4085 PortNumber is invalid or PortFeature is invalid.\r
4086 EFI_DEVICE_ERROR\r
4087 Can't read register\r
4088--*/ \r
4089{\r
4090 USB_HC_DEV *HcDev;\r
4091\r
4092 HcDev = USB2_HC_DEV_FROM_THIS (This);\r
4093 return UHCIClearRootHubPortFeature(\r
4094 &HcDev->UsbHc, \r
4095 PortNumber, \r
4096 PortFeature\r
4097 );\r
4098}\r
4099\r
878ddf1f 4100VOID\r
4101EFIAPI\r
4102MonitorInterruptTrans (\r
4103 IN EFI_EVENT Event,\r
4104 IN VOID *Context\r
4105 )\r
4106/*++\r
4107 Routine Description:\r
4108 Interrupt transfer periodic check handler\r
4109 Arguments:\r
4110 Event - Interrupt event\r
4111 Contex - Pointer to USB_HC_DEV\r
4112 Returns:\r
4113 None\r
4114--*/ \r
4115{\r
4116\r
4117 USB_HC_DEV *HcDev;\r
4118 INTERRUPT_LIST *PtrList;\r
4119 LIST_ENTRY *Link;\r
4120 UINT32 Result;\r
4121 VOID *DataBuffer;\r
4122 UINTN DataLen;\r
4123 UINTN ActualLen;\r
4124 UINTN ErrTDPos;\r
878ddf1f 4125 LIST_ENTRY *NextLink;\r
4126\r
4127 HcDev = (USB_HC_DEV *) Context;\r
878ddf1f 4128\r
4129 //\r
4130 // interrupt transfer list is empty, means that no interrupt transfer\r
4131 // is submitted by far.\r
4132 //\r
4133 if (IsListEmpty (&(HcDev->InterruptListHead))) {\r
4134 return ;\r
4135 }\r
4136\r
4137 NextLink = HcDev->InterruptListHead.ForwardLink;\r
4138 do {\r
4139\r
4140 Link = NextLink;\r
4141 NextLink = Link->ForwardLink;\r
4142\r
4143 PtrList = INTERRUPT_LIST_FROM_LINK (Link);\r
4144\r
4145 //\r
4146 // get TD execution results.\r
4147 // ErrTDPos is zero-based value indicating the first error TD's position\r
4148 // in the TDs' list.\r
4149 // This value is only valid when Result not equal NOERROR.\r
4150 //\r
4151 ExecuteAsyncINTTDs (\r
4152 HcDev,\r
4153 PtrList,\r
4154 &Result,\r
4155 &ErrTDPos,\r
4156 &ActualLen\r
4157 );\r
4158\r
4159 //\r
4160 // interrupt transfer has not been executed yet.\r
4161 //\r
4162 if (((Result & EFI_USB_ERR_NAK) == EFI_USB_ERR_NAK) ||\r
4163 ((Result & EFI_USB_ERR_NOTEXECUTE) == EFI_USB_ERR_NOTEXECUTE)) {\r
4164 continue;\r
4165 }\r
4166 //\r
4167 // get actual data length transferred data and its data length.\r
4168 //\r
4169 DataLen = ActualLen;\r
4170 DataBuffer = AllocatePool (DataLen);\r
4171 if (DataBuffer == NULL) {\r
4172 return ;\r
4173 }\r
4174\r
4175 CopyMem (\r
4176 DataBuffer,\r
4177 PtrList->PtrFirstTD->pTDBuffer,\r
4178 DataLen\r
4179 );\r
4180\r
4181 //\r
4182 // only if interrupt endpoint responds\r
4183 // and the interrupt transfer stops because of completion\r
4184 // or error, then we will call callback function.\r
4185 //\r
4186 if (Result == EFI_USB_NOERROR) {\r
4187 //\r
4188 // add for real platform debug\r
4189 //\r
4190 if (PtrList->InterruptCallBack != NULL) {\r
4191 (PtrList->InterruptCallBack) (\r
4192 DataBuffer,\r
4193 DataLen,\r
4194 PtrList->InterruptContext,\r
4195 Result\r
4196 );\r
4197 }\r
4198\r
4199 if (DataBuffer) {\r
4200 gBS->FreePool (DataBuffer);\r
4201 }\r
4202 \r
4203 //\r
4204 // update should done after data buffer got.\r
4205 //\r
4206 UpdateAsyncINTQHTDs (PtrList, Result, (UINT32) ErrTDPos);\r
4207\r
4208 } else {\r
4209\r
4210 DEBUG ((EFI_D_ERROR, "interrupt transfer error code is %x\n", Result));\r
4211\r
4212 if (DataBuffer) {\r
4213 gBS->FreePool (DataBuffer);\r
4214 }\r
4215 //\r
4216 // leave error recovery to its related device driver.\r
4217 // A common case of the error recovery is to re-submit the interrupt\r
4218 // transfer.\r
4219 // When an interrupt transfer is re-submitted, its position in the linked\r
4220 // list is changed. It is inserted to the head of the linked list, while\r
4221 // this function scans the whole list from head to tail. Thus, the\r
4222 // re-submitted interrupt transfer's callback function will not be called\r
4223 // again in this round.\r
4224 //\r
4225 if (PtrList->InterruptCallBack != NULL) {\r
4226 (PtrList->InterruptCallBack) (\r
4227 NULL,\r
4228 0,\r
4229 PtrList->InterruptContext,\r
4230 Result\r
4231 );\r
4232 }\r
4233 }\r
4234 } while (NextLink != &(HcDev->InterruptListHead));\r
4235\r
4236}\r