Fixed potential issues to release resources when error occurs.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UhciDxe / Uhci.c
CommitLineData
913cb9dc 1/** @file\r
2\r
3Copyright (c) 2004 - 2007, 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 The UHCI driver model and HC protocol routines.\r
19\r
20Revision History\r
21\r
22\r
23**/\r
24\r
25#include "Uhci.h"\r
26\r
27\r
28/**\r
29 Provides software reset for the USB host controller.\r
30\r
31 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
32 Attributes: A bit mask of the reset operation to perform.\r
33\r
34 @return EFI_SUCCESS : The reset operation succeeded.\r
35 @return EFI_INVALID_PARAMETER : Attributes is not valid.\r
36 @return EFI_DEVICE_ERROR : An error was encountered while attempting\r
37 @return to perform the reset operation.\r
38\r
39**/\r
40STATIC\r
41EFI_STATUS\r
42EFIAPI\r
43UhciReset (\r
44 IN EFI_USB_HC_PROTOCOL *This,\r
45 IN UINT16 Attributes\r
46 )\r
47{\r
48 USB_HC_DEV *Uhc;\r
49 EFI_TPL OldTpl;\r
50\r
51 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
52 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
53\r
54 switch (Attributes) {\r
55 case EFI_USB_HC_RESET_GLOBAL:\r
56 //\r
57 // Stop schedule and set the Global Reset bit in the command register\r
58 //\r
41e8ff27 59 UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
913cb9dc 60 UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET);\r
61\r
41e8ff27 62 gBS->Stall (UHC_ROOT_PORT_RESET_STALL);\r
913cb9dc 63\r
64 //\r
65 // Clear the Global Reset bit to zero.\r
66 //\r
67 UhciClearRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET);\r
68\r
41e8ff27 69 gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL);\r
913cb9dc 70 break;\r
71\r
72 case EFI_USB_HC_RESET_HOST_CONTROLLER:\r
73 //\r
74 // Stop schedule and set Host Controller Reset bit to 1\r
75 //\r
41e8ff27 76 UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
913cb9dc 77 UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_HCRESET);\r
78\r
41e8ff27 79 gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL);\r
913cb9dc 80 break;\r
81\r
82 default:\r
83 goto ON_INVAILD_PARAMETER;\r
84 }\r
68246fa8 85\r
913cb9dc 86 //\r
87 // Delete all old transactions on the USB bus, then\r
88 // reinitialize the frame list\r
89 //\r
90 UhciFreeAllAsyncReq (Uhc);\r
91 UhciDestoryFrameList (Uhc);\r
92 UhciInitFrameList (Uhc);\r
93\r
94 gBS->RestoreTPL (OldTpl);\r
68246fa8 95\r
913cb9dc 96 return EFI_SUCCESS;\r
97\r
98ON_INVAILD_PARAMETER:\r
68246fa8 99\r
913cb9dc 100 gBS->RestoreTPL (OldTpl);\r
68246fa8 101\r
913cb9dc 102 return EFI_INVALID_PARAMETER;\r
103}\r
104\r
105\r
106/**\r
107 Retrieves current state of the USB host controller.\r
108\r
109 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
110 State : A pointer to the EFI_USB_HC_STATE data structure that\r
111 indicates current state of the USB host controller.\r
112\r
113 @return EFI_SUCCESS : State was returned\r
114 @return EFI_INVALID_PARAMETER : State is NULL.\r
115 @return EFI_DEVICE_ERROR : An error was encountered\r
116\r
117**/\r
118STATIC\r
119EFI_STATUS\r
120EFIAPI\r
121UhciGetState (\r
122 IN EFI_USB_HC_PROTOCOL *This,\r
123 OUT EFI_USB_HC_STATE *State\r
124 )\r
125{\r
126 USB_HC_DEV *Uhc;\r
127 UINT16 UsbSts;\r
128 UINT16 UsbCmd;\r
129\r
130 if (State == NULL) {\r
131 return EFI_INVALID_PARAMETER;\r
132 }\r
133\r
134 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
135\r
136 UsbCmd = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
137 UsbSts = UhciReadReg (Uhc->PciIo, USBSTS_OFFSET);\r
138\r
139 if (UsbCmd & USBCMD_EGSM) {\r
140 *State = EfiUsbHcStateSuspend;\r
141\r
142 } else if ((UsbSts & USBSTS_HCH) != 0) {\r
143 *State = EfiUsbHcStateHalt;\r
144\r
145 } else {\r
146 *State = EfiUsbHcStateOperational;\r
147 }\r
148\r
149 return EFI_SUCCESS;\r
150}\r
151\r
152\r
153/**\r
154 Sets the USB host controller to a specific state.\r
155\r
156 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
157 State : Indicates the state of the host controller that will be set.\r
158\r
159 @return EFI_SUCCESS : The USB host controller was successfully set\r
160 @return EFI_INVALID_PARAMETER : State is invalid.\r
161 @return EFI_DEVICE_ERROR : Failed to set the state specified\r
162\r
163**/\r
164STATIC\r
165EFI_STATUS\r
166EFIAPI\r
167UhciSetState (\r
168 IN EFI_USB_HC_PROTOCOL *This,\r
169 IN EFI_USB_HC_STATE State\r
170 )\r
171{\r
172 EFI_USB_HC_STATE CurState;\r
173 USB_HC_DEV *Uhc;\r
174 EFI_TPL OldTpl;\r
175 EFI_STATUS Status;\r
176 UINT16 UsbCmd;\r
177\r
178 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
179 Status = UhciGetState (This, &CurState);\r
180\r
181 if (EFI_ERROR (Status)) {\r
182 return EFI_DEVICE_ERROR;\r
183 }\r
184\r
185 if (CurState == State) {\r
186 return EFI_SUCCESS;\r
187 }\r
188\r
189 Status = EFI_SUCCESS;\r
190 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
191\r
192 switch (State) {\r
193 case EfiUsbHcStateHalt:\r
41e8ff27 194 Status = UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
913cb9dc 195 break;\r
196\r
197 case EfiUsbHcStateOperational:\r
198 UsbCmd = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
199\r
200 if (CurState == EfiUsbHcStateHalt) {\r
201 //\r
202 // Set Run/Stop bit to 1, also set the bandwidht reclamation\r
203 // point to 64 bytes\r
204 //\r
205 UsbCmd |= USBCMD_RS | USBCMD_MAXP;\r
206 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
207\r
208 } else if (CurState == EfiUsbHcStateSuspend) {\r
209 //\r
210 // If FGR(Force Global Resume) bit is 0, set it\r
211 //\r
212 if ((UsbCmd & USBCMD_FGR) == 0) {\r
213 UsbCmd |= USBCMD_FGR;\r
214 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
215 }\r
68246fa8 216\r
913cb9dc 217 //\r
218 // wait 20ms to let resume complete (20ms is specified by UHCI spec)\r
219 //\r
41e8ff27 220 gBS->Stall (UHC_FORCE_GLOBAL_RESUME_STALL);\r
913cb9dc 221\r
222 //\r
223 // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0\r
224 //\r
225 UsbCmd &= ~USBCMD_FGR;\r
226 UsbCmd &= ~USBCMD_EGSM;\r
227 UsbCmd |= USBCMD_RS;\r
228 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
229 }\r
230\r
231 break;\r
232\r
233 case EfiUsbHcStateSuspend:\r
234 Status = UhciSetState (This, EfiUsbHcStateHalt);\r
235\r
236 if (EFI_ERROR (Status)) {\r
237 Status = EFI_DEVICE_ERROR;\r
238 goto ON_EXIT;\r
239 }\r
68246fa8 240\r
913cb9dc 241 //\r
242 // Set Enter Global Suspend Mode bit to 1.\r
243 //\r
244 UsbCmd = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
245 UsbCmd |= USBCMD_EGSM;\r
246 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
247 break;\r
248\r
249 default:\r
250 Status = EFI_INVALID_PARAMETER;\r
251 break;\r
252 }\r
253\r
254ON_EXIT:\r
255 gBS->RestoreTPL (OldTpl);\r
256 return Status;\r
257}\r
258\r
259\r
260/**\r
261 Retrieves the number of root hub ports.\r
262\r
263 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
264 PortNumber : A pointer to the number of the root hub ports.\r
265\r
266 @return EFI_SUCCESS : The port number was retrieved successfully.\r
267 @return EFI_INVALID_PARAMETER : PortNumber is NULL.\r
268 @return EFI_DEVICE_ERROR : An error was encountered\r
269\r
270**/\r
271STATIC\r
272EFI_STATUS\r
273EFIAPI\r
274UhciGetRootHubPortNumber (\r
275 IN EFI_USB_HC_PROTOCOL *This,\r
276 OUT UINT8 *PortNumber\r
277 )\r
278{\r
279 USB_HC_DEV *Uhc;\r
280 UINT32 Offset;\r
281 UINT16 PortSC;\r
282 UINT32 Index;\r
283\r
284 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
285\r
286 if (PortNumber == NULL) {\r
287 return EFI_INVALID_PARAMETER;\r
288 }\r
289\r
290 *PortNumber = 0;\r
291\r
292 for (Index = 0; Index < USB_MAX_ROOTHUB_PORT; Index++) {\r
293 Offset = USBPORTSC_OFFSET + Index * 2;\r
294 PortSC = UhciReadReg (Uhc->PciIo, Offset);\r
295\r
296 //\r
297 // Port status's bit 7 is reserved and always returns 1 if\r
298 // the port number is valid. Intel's UHCI (in EHCI controller)\r
299 // returns 0 in this bit if port number is invalid. Also, if\r
300 // PciIo IoRead returns error, 0xFFFF is returned to caller.\r
301 //\r
302 if (((PortSC & 0x80) != 0) && (PortSC != 0xFFFF)) {\r
303 (*PortNumber)++;\r
304 }\r
305 }\r
306\r
307 Uhc->RootPorts = *PortNumber;\r
308\r
309 UHCI_DEBUG (("UhciGetRootHubPortNumber: %d ports\n", Uhc->RootPorts));\r
310 return EFI_SUCCESS;\r
311}\r
312\r
313\r
314/**\r
315 Retrieves the current status of a USB root hub port.\r
316\r
317 This : A pointer to the EFI_USB_HC_PROTOCOL.\r
318 PortNumber : Specifies the root hub port. This value is zero-based.\r
319 PortStatus : A pointer to the current port status bits and port status change bits.\r
320\r
321 @return EFI_SUCCESS : The port status was returned in PortStatus.\r
322 @return EFI_INVALID_PARAMETER : PortNumber is invalid.\r
323 @return EFI_DEVICE_ERROR : Can't read register\r
324\r
325**/\r
326EFI_STATUS\r
327EFIAPI\r
328UhciGetRootHubPortStatus (\r
329 IN EFI_USB_HC_PROTOCOL *This,\r
330 IN UINT8 PortNumber,\r
331 OUT EFI_USB_PORT_STATUS *PortStatus\r
332 )\r
333{\r
334 USB_HC_DEV *Uhc;\r
335 UINT32 Offset;\r
336 UINT16 PortSC;\r
337\r
338 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
339\r
340 if (PortStatus == NULL) {\r
341 return EFI_INVALID_PARAMETER;\r
342 }\r
343\r
344 if (PortNumber >= Uhc->RootPorts) {\r
345 return EFI_INVALID_PARAMETER;\r
346 }\r
347\r
348 Offset = USBPORTSC_OFFSET + PortNumber * 2;\r
349 PortStatus->PortStatus = 0;\r
350 PortStatus->PortChangeStatus = 0;\r
351\r
352 PortSC = UhciReadReg (Uhc->PciIo, Offset);\r
353\r
354 if (PortSC & USBPORTSC_CCS) {\r
355 PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;\r
356 }\r
357\r
358 if (PortSC & USBPORTSC_PED) {\r
359 PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;\r
360 }\r
361\r
362 if (PortSC & USBPORTSC_SUSP) {\r
363 UHCI_DEBUG (("UhciGetRootHubPortStatus: port %d is suspended\n", PortNumber));\r
364 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
365 }\r
366\r
367 if (PortSC & USBPORTSC_PR) {\r
368 PortStatus->PortStatus |= USB_PORT_STAT_RESET;\r
369 }\r
370\r
371 if (PortSC & USBPORTSC_LSDA) {\r
372 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
373 }\r
374\r
375 //\r
376 // CHC will always return one in port owner bit\r
377 //\r
378 PortStatus->PortStatus |= USB_PORT_STAT_OWNER;\r
379\r
380 if (PortSC & USBPORTSC_CSC) {\r
381 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;\r
382 }\r
383\r
384 if (PortSC & USBPORTSC_PEDC) {\r
385 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;\r
386 }\r
387\r
388 return EFI_SUCCESS;\r
389}\r
390\r
391\r
392/**\r
393 Sets a feature for the specified root hub port.\r
394\r
395 This : A pointer to the EFI_USB_HC_PROTOCOL.\r
396 PortNumber : Specifies the root hub port whose feature\r
397 is requested to be set.\r
398 PortFeature : Indicates the feature selector associated\r
399 with the feature set request.\r
400\r
401 @return EFI_SUCCESS : The feature was set for the port.\r
402 @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
403 @return EFI_DEVICE_ERROR : Can't read register\r
404\r
405**/\r
406STATIC\r
407EFI_STATUS\r
408EFIAPI\r
409UhciSetRootHubPortFeature (\r
410 IN EFI_USB_HC_PROTOCOL *This,\r
411 IN UINT8 PortNumber,\r
412 IN EFI_USB_PORT_FEATURE PortFeature\r
413 )\r
414{\r
415 USB_HC_DEV *Uhc;\r
416 EFI_TPL OldTpl;\r
417 UINT32 Offset;\r
418 UINT16 PortSC;\r
419 UINT16 Command;\r
420\r
421 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
422\r
423 if (PortNumber >= Uhc->RootPorts) {\r
424 return EFI_INVALID_PARAMETER;\r
425 }\r
426\r
427 Offset = USBPORTSC_OFFSET + PortNumber * 2;\r
428\r
429 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
430 PortSC = UhciReadReg (Uhc->PciIo, Offset);\r
431\r
432 switch (PortFeature) {\r
433 case EfiUsbPortSuspend:\r
434 Command = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
435 if (!(Command & USBCMD_EGSM)) {\r
436 //\r
437 // if global suspend is not active, can set port suspend\r
438 //\r
439 PortSC &= 0xfff5;\r
440 PortSC |= USBPORTSC_SUSP;\r
441 }\r
442 break;\r
443\r
444 case EfiUsbPortReset:\r
445 PortSC &= 0xfff5;\r
446 PortSC |= USBPORTSC_PR;\r
447 break;\r
448\r
449 case EfiUsbPortPower:\r
450 //\r
451 // No action\r
452 //\r
453 break;\r
454\r
455 case EfiUsbPortEnable:\r
456 PortSC &= 0xfff5;\r
457 PortSC |= USBPORTSC_PED;\r
458 break;\r
459\r
460 default:\r
461 gBS->RestoreTPL (OldTpl);\r
462 return EFI_INVALID_PARAMETER;\r
463 }\r
464\r
465 UhciWriteReg (Uhc->PciIo, Offset, PortSC);\r
466 gBS->RestoreTPL (OldTpl);\r
467\r
468 return EFI_SUCCESS;\r
469}\r
470\r
471\r
472/**\r
473 Clears a feature for the specified root hub port.\r
474\r
475 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
476 PortNumber : Specifies the root hub port whose feature\r
477 is requested to be cleared.\r
478 PortFeature : Indicates the feature selector associated with the\r
479 feature clear request.\r
480\r
481 @return EFI_SUCCESS : The feature was cleared for the port.\r
482 @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
483 @return EFI_DEVICE_ERROR : Can't read register\r
484\r
485**/\r
486STATIC\r
487EFI_STATUS\r
488EFIAPI\r
489UhciClearRootHubPortFeature (\r
490 IN EFI_USB_HC_PROTOCOL *This,\r
491 IN UINT8 PortNumber,\r
492 IN EFI_USB_PORT_FEATURE PortFeature\r
493 )\r
494{\r
495 USB_HC_DEV *Uhc;\r
496 EFI_TPL OldTpl;\r
497 UINT32 Offset;\r
498 UINT16 PortSC;\r
499\r
500 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
501\r
502 if (PortNumber >= Uhc->RootPorts) {\r
503 return EFI_INVALID_PARAMETER;\r
504 }\r
505\r
506 Offset = USBPORTSC_OFFSET + PortNumber * 2;\r
507\r
508 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
509 PortSC = UhciReadReg (Uhc->PciIo, Offset);\r
510\r
511 switch (PortFeature) {\r
512 case EfiUsbPortEnable:\r
513 PortSC &= 0xfff5;\r
514 PortSC &= ~USBPORTSC_PED;\r
515 break;\r
516\r
517 case EfiUsbPortSuspend:\r
518 //\r
519 // Cause a resume on the specified port if in suspend mode.\r
520 //\r
521 PortSC &= 0xfff5;\r
522 PortSC &= ~USBPORTSC_SUSP;\r
523 break;\r
524\r
525 case EfiUsbPortPower:\r
526 //\r
527 // No action\r
528 //\r
529 break;\r
530\r
531 case EfiUsbPortReset:\r
532 PortSC &= 0xfff5;\r
533 PortSC &= ~USBPORTSC_PR;\r
534 break;\r
535\r
536 case EfiUsbPortConnectChange:\r
537 PortSC &= 0xfff5;\r
538 PortSC |= USBPORTSC_CSC;\r
539 break;\r
540\r
541 case EfiUsbPortEnableChange:\r
542 PortSC &= 0xfff5;\r
543 PortSC |= USBPORTSC_PEDC;\r
544 break;\r
545\r
546 case EfiUsbPortSuspendChange:\r
547 //\r
548 // Root hub does not support this\r
549 //\r
550 break;\r
551\r
552 case EfiUsbPortOverCurrentChange:\r
553 //\r
554 // Root hub does not support this\r
555 //\r
556 break;\r
557\r
558 case EfiUsbPortResetChange:\r
559 //\r
560 // Root hub does not support this\r
561 //\r
562 break;\r
563\r
564 default:\r
565 gBS->RestoreTPL (OldTpl);\r
566 return EFI_INVALID_PARAMETER;\r
567 }\r
568\r
569 UhciWriteReg (Uhc->PciIo, Offset, PortSC);\r
570 gBS->RestoreTPL (OldTpl);\r
571\r
572 return EFI_SUCCESS;\r
573}\r
574\r
575\r
576/**\r
577 Submits control transfer to a target USB device.\r
578\r
579 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
580 DeviceAddress : Usb device address\r
581 IsSlowDevice : Whether the device is of slow speed or full speed\r
582 MaximumPacketLength : maximum packet size of the default control endpoint\r
583 Request : USB device request to send\r
584 TransferDirection : Specifies the data direction for the transfer.\r
585 Data : Data buffer to transmit from or receive into\r
586 DataLength : Number of bytes of the data\r
587 TimeOut : Maximum time, in microseconds\r
588 TransferResult : Return result in this\r
589\r
590 @return EFI_SUCCESS : Transfer was completed successfully.\r
591 @return EFI_OUT_OF_RESOURCES : Failed due to a lack of resources.\r
592 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
593 @return EFI_TIMEOUT : Failed due to timeout.\r
594 @return EFI_DEVICE_ERROR : Failed due to host controller or device error.\r
595\r
596**/\r
597STATIC\r
598EFI_STATUS\r
599EFIAPI\r
600UhciControlTransfer (\r
601 IN EFI_USB_HC_PROTOCOL *This,\r
602 IN UINT8 DeviceAddress,\r
603 IN BOOLEAN IsSlowDevice,\r
604 IN UINT8 MaximumPacketLength,\r
605 IN EFI_USB_DEVICE_REQUEST *Request,\r
606 IN EFI_USB_DATA_DIRECTION TransferDirection,\r
607 IN OUT VOID *Data, OPTIONAL\r
608 IN OUT UINTN *DataLength, OPTIONAL\r
609 IN UINTN TimeOut,\r
610 OUT UINT32 *TransferResult\r
611 )\r
612{\r
613 USB_HC_DEV *Uhc;\r
614 UHCI_TD_SW *TDs;\r
615 EFI_TPL OldTpl;\r
616 EFI_STATUS Status;\r
617 UHCI_QH_RESULT QhResult;\r
618 UINT8 PktId;\r
619 UINT8 *RequestPhy;\r
620 VOID *RequestMap;\r
621 UINT8 *DataPhy;\r
622 VOID *DataMap;\r
623\r
624 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
625 TDs = NULL;\r
626 DataPhy = NULL;\r
627 DataMap = NULL;\r
628 RequestPhy = NULL;\r
629 RequestMap = NULL;\r
630\r
631 //\r
632 // Parameters Checking\r
633 //\r
634 if (Request == NULL || TransferResult == NULL) {\r
635 return EFI_INVALID_PARAMETER;\r
636 }\r
637\r
638 if (IsSlowDevice && (MaximumPacketLength != 8)) {\r
639 return EFI_INVALID_PARAMETER;\r
640 }\r
641\r
642 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&\r
643 (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {\r
644\r
645 return EFI_INVALID_PARAMETER;\r
646 }\r
647\r
648 if ((TransferDirection != EfiUsbNoData) && (DataLength == NULL)) {\r
649 return EFI_INVALID_PARAMETER;\r
650 }\r
651\r
652 *TransferResult = EFI_USB_ERR_SYSTEM;\r
653 Status = EFI_DEVICE_ERROR;\r
654\r
655 //\r
656 // If errors exist that cause host controller halt,\r
657 // clear status then return EFI_DEVICE_ERROR.\r
658 //\r
659 UhciAckAllInterrupt (Uhc);\r
660\r
661 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
662 return EFI_DEVICE_ERROR;\r
663 }\r
664\r
665 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
666\r
667 //\r
668 // Map the Request and data for bus master access,\r
669 // then create a list of TD for this transfer\r
670 //\r
671 Status = UhciMapUserRequest (Uhc, Request, &RequestPhy, &RequestMap);\r
672\r
673 if (EFI_ERROR (Status)) {\r
674 goto ON_EXIT;\r
675 }\r
676\r
677 Status = UhciMapUserData (Uhc, TransferDirection, Data, DataLength, &PktId, &DataPhy, &DataMap);\r
678\r
679 if (EFI_ERROR (Status)) {\r
680 Uhc->PciIo->Unmap (Uhc->PciIo, RequestMap);\r
681 goto ON_EXIT;\r
682 }\r
683\r
684 TDs = UhciCreateCtrlTds (\r
685 Uhc,\r
686 DeviceAddress,\r
687 PktId,\r
688 RequestPhy,\r
689 DataPhy,\r
690 *DataLength,\r
691 MaximumPacketLength,\r
692 IsSlowDevice\r
693 );\r
694\r
695 if (TDs == NULL) {\r
696 Status = EFI_OUT_OF_RESOURCES;\r
697 goto UNMAP_DATA;\r
698 }\r
699\r
700 //\r
701 // According to the speed of the end point, link\r
702 // the TD to corrosponding queue head, then check\r
703 // the execution result\r
704 //\r
705 UhciLinkTdToQh (Uhc->CtrlQh, TDs);\r
706 Status = UhciExecuteTransfer (Uhc, Uhc->CtrlQh, TDs, TimeOut, IsSlowDevice, &QhResult);\r
707 UhciUnlinkTdFromQh (Uhc->CtrlQh, TDs);\r
708\r
709 Uhc->PciIo->Flush (Uhc->PciIo);\r
710\r
711 *TransferResult = QhResult.Result;\r
712\r
713 if (DataLength != NULL) {\r
714 *DataLength = QhResult.Complete;\r
715 }\r
716\r
717 UhciDestoryTds (Uhc, TDs);\r
718\r
719UNMAP_DATA:\r
720 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
721 Uhc->PciIo->Unmap (Uhc->PciIo, RequestMap);\r
722\r
723ON_EXIT:\r
724 gBS->RestoreTPL (OldTpl);\r
725 return Status;\r
726}\r
727\r
728\r
729/**\r
730 Submits bulk transfer to a bulk endpoint of a USB device.\r
731\r
732 This :A pointer to the EFI_USB_HC_PROTOCOL instance.\r
733 DeviceAddress : Usb device address\r
734 EndPointAddress : Endpoint number and endpoint direction\r
735 MaximumPacketLength : Maximum packet size of the target endpoint\r
736 Data : Data buffer to transmit from or receive into\r
737 DataLength : Length of the data buffer\r
738 DataToggle : On input, data toggle to use, on output, the next toggle\r
739 TimeOut : Indicates the maximum time\r
740 TransferResult : Variable to receive the transfer result\r
741\r
742 @return EFI_SUCCESS : The bulk transfer was completed successfully.\r
743 @return EFI_OUT_OF_RESOURCES : Failed due to lack of resource.\r
744 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
745 @return EFI_TIMEOUT : Failed due to timeout.\r
746 @return EFI_DEVICE_ERROR : Failed due to host controller or device error.\r
747\r
748**/\r
749STATIC\r
750EFI_STATUS\r
751EFIAPI\r
752UhciBulkTransfer (\r
753 IN EFI_USB_HC_PROTOCOL *This,\r
754 IN UINT8 DeviceAddress,\r
755 IN UINT8 EndPointAddress,\r
756 IN UINT8 MaximumPacketLength,\r
757 IN OUT VOID *Data,\r
758 IN OUT UINTN *DataLength,\r
759 IN OUT UINT8 *DataToggle,\r
760 IN UINTN TimeOut,\r
761 OUT UINT32 *TransferResult\r
762 )\r
763{\r
764 EFI_USB_DATA_DIRECTION Direction;\r
765 EFI_TPL OldTpl;\r
766 USB_HC_DEV *Uhc;\r
767 UHCI_TD_SW *TDs;\r
768 UHCI_QH_SW *BulkQh;\r
769 UHCI_QH_RESULT QhResult;\r
770 EFI_STATUS Status;\r
771 UINT8 PktId;\r
772 UINT8 *DataPhy;\r
773 VOID *DataMap;\r
774\r
775 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
776 DataPhy = NULL;\r
777 DataMap = NULL;\r
778\r
779 if ((DataLength == NULL) || (Data == NULL) || (TransferResult == NULL)) {\r
780 return EFI_INVALID_PARAMETER;\r
781 }\r
782\r
783 if (*DataLength == 0) {\r
784 return EFI_INVALID_PARAMETER;\r
785 }\r
786\r
787 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
788 return EFI_INVALID_PARAMETER;\r
789 }\r
790\r
791 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&\r
792 (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {\r
793 return EFI_INVALID_PARAMETER;\r
794 }\r
795\r
796 *TransferResult = EFI_USB_ERR_SYSTEM;\r
797 Status = EFI_OUT_OF_RESOURCES;\r
798\r
799 //\r
800 // If has errors that cause host controller halt,\r
801 // then return EFI_DEVICE_ERROR directly.\r
802 //\r
803 UhciAckAllInterrupt (Uhc);\r
804\r
805 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
806 return EFI_DEVICE_ERROR;\r
807 }\r
808\r
809 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
810\r
811 //\r
812 // Map the source data buffer for bus master access,\r
813 // then create a list of TDs\r
814 //\r
815 if (EndPointAddress & 0x80) {\r
816 Direction = EfiUsbDataIn;\r
817 } else {\r
818 Direction = EfiUsbDataOut;\r
819 }\r
820\r
821 Status = UhciMapUserData (Uhc, Direction, Data, DataLength, &PktId, &DataPhy, &DataMap);\r
822\r
823 if (EFI_ERROR (Status)) {\r
824 goto ON_EXIT;\r
825 }\r
826\r
827 Status = EFI_OUT_OF_RESOURCES;\r
828 TDs = UhciCreateBulkOrIntTds (\r
829 Uhc,\r
830 DeviceAddress,\r
831 EndPointAddress,\r
832 PktId,\r
833 DataPhy,\r
834 *DataLength,\r
835 DataToggle,\r
836 MaximumPacketLength,\r
837 FALSE\r
838 );\r
839\r
840 if (TDs == NULL) {\r
841 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
842 goto ON_EXIT;\r
843 }\r
844\r
845\r
846 //\r
847 // Link the TDs to bulk queue head. According to the platfore\r
848 // defintion of UHCI_NO_BW_RECLAMATION, BulkQh is either configured\r
849 // to do full speed bandwidth reclamation or not.\r
850 //\r
851 BulkQh = Uhc->BulkQh;\r
852\r
853 UhciLinkTdToQh (BulkQh, TDs);\r
854 Status = UhciExecuteTransfer (Uhc, BulkQh, TDs, TimeOut, FALSE, &QhResult);\r
855 UhciUnlinkTdFromQh (BulkQh, TDs);\r
856\r
857 Uhc->PciIo->Flush (Uhc->PciIo);\r
858\r
859 *TransferResult = QhResult.Result;\r
860 *DataToggle = QhResult.NextToggle;\r
861 *DataLength = QhResult.Complete;\r
862\r
863 UhciDestoryTds (Uhc, TDs);\r
864 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
865\r
866ON_EXIT:\r
867 gBS->RestoreTPL (OldTpl);\r
868 return Status;\r
869}\r
870\r
871\r
872/**\r
873 Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.\r
874\r
875 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
876 DeviceAddress : Target device address\r
877 EndPointAddress : Endpoint number with direction\r
878 IsSlowDevice : Whether the target device is slow device or full-speed device.\r
879 MaximumPacketLength : Maximum packet size of the target endpoint\r
880 IsNewTransfer : If TRUE, submit a new async interrupt transfer, otherwise\r
881 cancel an existed one\r
882 DataToggle : On input, the data toggle to use; On output, next data toggle\r
883 PollingInterval : Interrupt poll rate in milliseconds\r
884 DataLength : Length of data to receive\r
885 CallBackFunction : Function to call periodically\r
886 Context : User context\r
887\r
888 @return EFI_SUCCESS : Request is submitted or cancelled\r
889 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
890 @return EFI_OUT_OF_RESOURCES : Failed due to a lack of resources.\r
891 @return EFI_DEVICE_ERROR : Failed to due to device error\r
892\r
893**/\r
894STATIC\r
895EFI_STATUS\r
896EFIAPI\r
897UhciAsyncInterruptTransfer (\r
898 IN EFI_USB_HC_PROTOCOL * This,\r
899 IN UINT8 DeviceAddress,\r
900 IN UINT8 EndPointAddress,\r
901 IN BOOLEAN IsSlowDevice,\r
902 IN UINT8 MaximumPacketLength,\r
903 IN BOOLEAN IsNewTransfer,\r
904 IN OUT UINT8 *DataToggle,\r
905 IN UINTN PollingInterval, OPTIONAL\r
906 IN UINTN DataLength, OPTIONAL\r
907 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, OPTIONAL\r
908 IN VOID *Context OPTIONAL\r
909 )\r
910{\r
911 USB_HC_DEV *Uhc;\r
912 UHCI_QH_SW *Qh;\r
913 UHCI_TD_SW *IntTds;\r
914 EFI_TPL OldTpl;\r
915 EFI_STATUS Status;\r
916 UINT8 *DataPtr;\r
917 UINT8 *DataPhy;\r
918 VOID *DataMap;\r
919 UINT8 PktId;\r
920\r
921 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
922 Qh = NULL;\r
923 IntTds = NULL;\r
924 DataPtr = NULL;\r
925 DataPhy = NULL;\r
926 DataMap = NULL;\r
927\r
928 if ((EndPointAddress & 0x80) == 0) {\r
929 return EFI_INVALID_PARAMETER;\r
930 }\r
931\r
932 //\r
933 // Delete Async interrupt transfer request\r
934 //\r
935 if (!IsNewTransfer) {\r
936 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
937 Status = UhciRemoveAsyncReq (Uhc, DeviceAddress, EndPointAddress, DataToggle);\r
938\r
939 gBS->RestoreTPL (OldTpl);\r
940 return Status;\r
941 }\r
942\r
943 if (PollingInterval < 1 || PollingInterval > 255) {\r
944 return EFI_INVALID_PARAMETER;\r
945 }\r
946\r
947 if (DataLength == 0) {\r
948 return EFI_INVALID_PARAMETER;\r
949 }\r
950\r
951 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
952 return EFI_INVALID_PARAMETER;\r
953 }\r
954\r
955 //\r
956 // If has errors that cause host controller halt,\r
957 // then return EFI_DEVICE_ERROR directly.\r
958 //\r
959 UhciAckAllInterrupt (Uhc);\r
960\r
961 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
962 return EFI_DEVICE_ERROR;\r
963 }\r
964\r
965 //\r
966 // Allocate and map source data buffer for bus master access.\r
967 //\r
968 DataPtr = AllocatePool (DataLength);\r
969\r
970 if (DataPtr == NULL) {\r
971 return EFI_OUT_OF_RESOURCES;\r
972 }\r
973\r
974 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
975\r
976 //\r
977 // Map the user data then create a queue head and\r
978 // list of TD for it.\r
979 //\r
980 Status = UhciMapUserData (\r
981 Uhc,\r
982 EfiUsbDataIn,\r
983 DataPtr,\r
984 &DataLength,\r
985 &PktId,\r
986 &DataPhy,\r
987 &DataMap\r
988 );\r
989\r
990 if (EFI_ERROR (Status)) {\r
991 goto FREE_DATA;\r
992 }\r
993\r
994 Qh = UhciCreateQh (Uhc, PollingInterval);\r
995\r
996 if (Qh == NULL) {\r
997 Status = EFI_OUT_OF_RESOURCES;\r
998 goto UNMAP_DATA;\r
999 }\r
1000\r
1001 IntTds = UhciCreateBulkOrIntTds (\r
1002 Uhc,\r
1003 DeviceAddress,\r
1004 EndPointAddress,\r
1005 PktId,\r
1006 DataPhy,\r
1007 DataLength,\r
1008 DataToggle,\r
1009 MaximumPacketLength,\r
1010 IsSlowDevice\r
1011 );\r
1012\r
1013 if (IntTds == NULL) {\r
1014 Status = EFI_OUT_OF_RESOURCES;\r
1015 goto DESTORY_QH;\r
1016 }\r
1017\r
1018 UhciLinkTdToQh (Qh, IntTds);\r
1019\r
1020 //\r
1021 // Save QH-TD structures to async Interrupt transfer list,\r
1022 // for monitor interrupt transfer execution routine use.\r
1023 //\r
1024 Status = UhciCreateAsyncReq (\r
1025 Uhc,\r
1026 Qh,\r
1027 IntTds,\r
1028 DeviceAddress,\r
1029 EndPointAddress,\r
1030 DataLength,\r
1031 PollingInterval,\r
1032 DataMap,\r
1033 DataPtr,\r
1034 CallBackFunction,\r
1035 Context,\r
1036 IsSlowDevice\r
1037 );\r
1038\r
1039 if (EFI_ERROR (Status)) {\r
1040 goto DESTORY_QH;\r
1041 }\r
1042\r
1043 UhciLinkQhToFrameList (Uhc->FrameBase, Qh);\r
1044\r
1045 gBS->RestoreTPL (OldTpl);\r
1046 return EFI_SUCCESS;\r
1047\r
1048DESTORY_QH:\r
1049 UsbHcFreeMem (Uhc->MemPool, Qh, sizeof (UHCI_QH_SW));\r
1050\r
1051UNMAP_DATA:\r
1052 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1053\r
1054FREE_DATA:\r
1055 gBS->FreePool (DataPtr);\r
1056 Uhc->PciIo->Flush (Uhc->PciIo);\r
1057\r
1058 gBS->RestoreTPL (OldTpl);\r
1059 return Status;\r
1060}\r
1061\r
1062\r
1063/**\r
1064 Submits synchronous interrupt transfer to an interrupt endpoint of a USB device.\r
1065\r
1066 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1067 DeviceAddress : Device address of the target USB device\r
1068 EndPointAddress : Endpoint number and direction\r
1069 IsSlowDevice : Whether the target device is of slow speed or full speed\r
1070 MaximumPacketLength : Maximum packet size of target endpoint\r
1071 Data : Data to transmit or receive\r
1072 DataLength : On input, data length to transmit or buffer size.\r
1073 On output, the number of bytes transferred.\r
1074 DataToggle : On input, data toggle to use; On output, next data toggle\r
1075 TimeOut : Maximum time, in microseconds, transfer is allowed to complete.\r
1076 TransferResult : Variable to receive transfer result\r
1077\r
1078 @return EFI_SUCCESS : Transfer was completed successfully.\r
1079 @return EFI_OUT_OF_RESOURCES : Failed due to lack of resource.\r
1080 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1081 @return EFI_TIMEOUT : Failed due to timeout.\r
1082 @return EFI_DEVICE_ERROR : Failed due to host controller or device error\r
1083\r
1084**/\r
1085STATIC\r
1086EFI_STATUS\r
1087EFIAPI\r
1088UhciSyncInterruptTransfer (\r
1089 IN EFI_USB_HC_PROTOCOL *This,\r
1090 IN UINT8 DeviceAddress,\r
1091 IN UINT8 EndPointAddress,\r
1092 IN BOOLEAN IsSlowDevice,\r
1093 IN UINT8 MaximumPacketLength,\r
1094 IN OUT VOID *Data,\r
1095 IN OUT UINTN *DataLength,\r
1096 IN OUT UINT8 *DataToggle,\r
1097 IN UINTN TimeOut,\r
1098 OUT UINT32 *TransferResult\r
1099 )\r
1100{\r
1101 EFI_STATUS Status;\r
1102 USB_HC_DEV *Uhc;\r
1103 UHCI_TD_SW *TDs;\r
1104 UHCI_QH_RESULT QhResult;\r
1105 EFI_TPL OldTpl;\r
1106 UINT8 *DataPhy;\r
1107 VOID *DataMap;\r
1108 UINT8 PktId;\r
1109\r
1110 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
1111 DataPhy = NULL;\r
1112 DataMap = NULL;\r
1113 TDs = NULL;\r
1114\r
1115 if ((DataLength == NULL) || (Data == NULL) || (TransferResult == NULL)) {\r
1116 return EFI_INVALID_PARAMETER;\r
1117 }\r
1118\r
1119 if ((EndPointAddress & 0x80) == 0) {\r
1120 return EFI_INVALID_PARAMETER;\r
1121 }\r
1122\r
1123 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
1124 return EFI_INVALID_PARAMETER;\r
1125 }\r
1126\r
1127 if ((*DataLength == 0) || (MaximumPacketLength > 64)) {\r
1128 return EFI_INVALID_PARAMETER;\r
1129 }\r
1130\r
1131 if (IsSlowDevice && (MaximumPacketLength > 8)) {\r
1132 return EFI_INVALID_PARAMETER;\r
1133 }\r
1134\r
1135 *TransferResult = EFI_USB_ERR_SYSTEM;\r
1136 Status = EFI_DEVICE_ERROR;\r
1137\r
1138\r
1139 UhciAckAllInterrupt (Uhc);\r
1140\r
1141 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
1142 return Status;\r
1143 }\r
1144\r
1145 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
1146\r
1147 //\r
1148 // Map the source data buffer for bus master access.\r
1149 // Create Tds list, then link it to the UHC's interrupt list\r
1150 //\r
1151 Status = UhciMapUserData (\r
1152 Uhc,\r
1153 EfiUsbDataIn,\r
1154 Data,\r
1155 DataLength,\r
1156 &PktId,\r
1157 &DataPhy,\r
1158 &DataMap\r
1159 );\r
1160\r
1161 if (EFI_ERROR (Status)) {\r
1162 goto ON_EXIT;\r
1163 }\r
1164\r
1165 TDs = UhciCreateBulkOrIntTds (\r
1166 Uhc,\r
1167 DeviceAddress,\r
1168 EndPointAddress,\r
1169 PktId,\r
1170 DataPhy,\r
1171 *DataLength,\r
1172 DataToggle,\r
1173 MaximumPacketLength,\r
1174 IsSlowDevice\r
1175 );\r
1176\r
1177 if (TDs == NULL) {\r
1178 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1179\r
1180 Status = EFI_OUT_OF_RESOURCES;\r
1181 goto ON_EXIT;\r
1182 }\r
1183\r
1184\r
1185 UhciLinkTdToQh (Uhc->SyncIntQh, TDs);\r
1186\r
1187 Status = UhciExecuteTransfer (Uhc, Uhc->SyncIntQh, TDs, TimeOut, IsSlowDevice, &QhResult);\r
1188\r
1189 UhciUnlinkTdFromQh (Uhc->SyncIntQh, TDs);\r
1190 Uhc->PciIo->Flush (Uhc->PciIo);\r
1191\r
1192 *TransferResult = QhResult.Result;\r
1193 *DataToggle = QhResult.NextToggle;\r
1194 *DataLength = QhResult.Complete;\r
1195\r
1196 UhciDestoryTds (Uhc, TDs);\r
1197 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1198\r
1199ON_EXIT:\r
1200 gBS->RestoreTPL (OldTpl);\r
1201 return Status;\r
1202}\r
1203\r
1204\r
1205/**\r
1206 Submits isochronous transfer to a target USB device.\r
1207\r
1208 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1209 DeviceAddress : Target device address\r
1210 EndPointAddress : End point address withdirection\r
1211 MaximumPacketLength : Maximum packet size of the endpoint\r
1212 Data : Data to transmit or receive\r
1213 DataLength : Bytes of the data\r
1214 TransferResult : Variable to receive the result\r
1215\r
1216 @return EFI_UNSUPPORTED\r
1217\r
1218**/\r
1219STATIC\r
1220EFI_STATUS\r
1221EFIAPI\r
1222UhciIsochronousTransfer (\r
1223 IN EFI_USB_HC_PROTOCOL *This,\r
1224 IN UINT8 DeviceAddress,\r
1225 IN UINT8 EndPointAddress,\r
1226 IN UINT8 MaximumPacketLength,\r
1227 IN OUT VOID *Data,\r
1228 IN UINTN DataLength,\r
1229 OUT UINT32 *TransferResult\r
1230 )\r
1231{\r
1232 return EFI_UNSUPPORTED;\r
1233}\r
1234\r
1235\r
1236/**\r
1237 Submits Async isochronous transfer to a target USB device.\r
1238\r
1239 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1240 DeviceAddress : Target device address\r
1241 EndPointAddress : End point address withdirection\r
1242 MaximumPacketLength : Maximum packet size of the endpoint\r
1243 Data : Data to transmit or receive\r
1244 IsochronousCallBack : Function to call when the transfer completes\r
1245 Context : User context\r
1246\r
1247 @return EFI_UNSUPPORTED\r
1248\r
1249**/\r
1250STATIC\r
1251EFI_STATUS\r
1252EFIAPI\r
1253UhciAsyncIsochronousTransfer (\r
1254 IN EFI_USB_HC_PROTOCOL * This,\r
1255 IN UINT8 DeviceAddress,\r
1256 IN UINT8 EndPointAddress,\r
1257 IN UINT8 MaximumPacketLength,\r
1258 IN OUT VOID *Data,\r
1259 IN UINTN DataLength,\r
1260 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
1261 IN VOID *Context OPTIONAL\r
1262 )\r
1263{\r
1264 return EFI_UNSUPPORTED;\r
1265}\r
1266\r
1267\r
1268\r
1269/**\r
1270 Provides software reset for the USB host controller according to UEFI 2.0 spec.\r
1271\r
1272 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1273 @param Attributes A bit mask of the reset operation to perform. See\r
1274 below for a list of the supported bit mask values.\r
1275\r
1276 @return EFI_SUCCESS : The reset operation succeeded.\r
1277 @return EFI_INVALID_PARAMETER : Attributes is not valid.\r
1278 @return EFI_UNSUPPORTED : This type of reset is not currently supported\r
1279 @return EFI_DEVICE_ERROR : Other errors\r
1280\r
1281**/\r
1282STATIC\r
1283EFI_STATUS\r
1284EFIAPI\r
1285Uhci2Reset (\r
1286 IN EFI_USB2_HC_PROTOCOL *This,\r
1287 IN UINT16 Attributes\r
1288 )\r
1289{\r
1290 USB_HC_DEV *UhciDev;\r
1291\r
1292 UhciDev = UHC_FROM_USB2_HC_PROTO (This);\r
1293\r
1294 if ((Attributes == EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG) ||\r
1295 (Attributes == EFI_USB_HC_RESET_HOST_WITH_DEBUG)) {\r
1296 return EFI_UNSUPPORTED;\r
1297 }\r
1298\r
1299 return UhciReset (&UhciDev->UsbHc, Attributes);\r
1300}\r
1301\r
1302\r
1303/**\r
1304 Retrieves current state of the USB host controller according to UEFI 2.0 spec.\r
1305\r
1306 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1307 @param State Variable to receive current device state\r
1308\r
1309 @return EFI_SUCCESS : The state is returned\r
1310 @return EFI_INVALID_PARAMETER : State is not valid.\r
1311 @return EFI_DEVICE_ERROR : Other errors2006\r
1312\r
1313**/\r
1314STATIC\r
1315EFI_STATUS\r
1316EFIAPI\r
1317Uhci2GetState (\r
1318 IN CONST EFI_USB2_HC_PROTOCOL *This,\r
1319 OUT EFI_USB_HC_STATE *State\r
1320 )\r
1321{\r
1322 USB_HC_DEV *Uhc;\r
1323\r
1324 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1325 return UhciGetState (&Uhc->UsbHc, State);\r
1326}\r
1327\r
1328\r
1329/**\r
1330 Sets the USB host controller to a specific state according to UEFI 2.0 spec.\r
1331\r
1332 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1333 @param State Indicates the state of the host controller that will\r
1334 be set.\r
1335\r
1336 @return EFI_SUCCESS : Host controller was successfully placed in the state\r
1337 @return EFI_INVALID_PARAMETER : State is invalid.\r
1338 @return EFI_DEVICE_ERROR : Failed to set the state\r
1339\r
1340**/\r
1341STATIC\r
1342EFI_STATUS\r
1343EFIAPI\r
1344Uhci2SetState (\r
1345 IN EFI_USB2_HC_PROTOCOL *This,\r
1346 IN EFI_USB_HC_STATE State\r
1347 )\r
1348{\r
1349 USB_HC_DEV *Uhc;\r
1350\r
1351 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1352 return UhciSetState (&Uhc->UsbHc, State);\r
1353}\r
1354\r
1355\r
1356/**\r
1357 Retrieves capabilities of USB host controller according to UEFI 2.0 spec.\r
1358\r
1359 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance\r
1360 @param MaxSpeed A pointer to the max speed USB host controller\r
1361 supports.\r
1362 @param PortNumber A pointer to the number of root hub ports.\r
1363 @param Is64BitCapable A pointer to an integer to show whether USB host\r
1364 controller supports 64-bit memory addressing.\r
1365\r
1366 @return EFI_SUCCESS : capabilities were retrieved successfully.\r
1367 @return EFI_INVALID_PARAMETER : MaxSpeed or PortNumber or Is64BitCapable is NULL.\r
1368 @return EFI_DEVICE_ERROR : An error was encountered\r
1369\r
1370**/\r
1371STATIC\r
1372EFI_STATUS\r
1373EFIAPI\r
1374Uhci2GetCapability (\r
1375 IN EFI_USB2_HC_PROTOCOL *This,\r
1376 OUT UINT8 *MaxSpeed,\r
1377 OUT UINT8 *PortNumber,\r
1378 OUT UINT8 *Is64BitCapable\r
1379 )\r
1380{\r
1381 USB_HC_DEV *Uhc;\r
1382\r
1383 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1384\r
1385 if ((NULL == MaxSpeed) || (NULL == PortNumber) || (NULL == Is64BitCapable)) {\r
1386 return EFI_INVALID_PARAMETER;\r
1387 }\r
1388\r
1389 *MaxSpeed = EFI_USB_SPEED_FULL;\r
1390 *Is64BitCapable = (UINT8) FALSE;\r
1391\r
1392 return UhciGetRootHubPortNumber (&Uhc->UsbHc, PortNumber);\r
1393}\r
1394\r
1395\r
1396/**\r
1397 Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.\r
1398\r
1399 @param This A pointer to the EFI_USB2_HC_PROTOCOL.\r
1400 @param PortNumber The port to get status\r
1401 @param PortStatus A pointer to the current port status bits and port\r
1402 status change bits.\r
1403\r
1404 @return EFI_SUCCESS : status of the USB root hub port was returned in PortStatus.\r
1405 @return EFI_INVALID_PARAMETER : PortNumber is invalid.\r
1406 @return EFI_DEVICE_ERROR : Can't read register\r
1407\r
1408**/\r
1409STATIC\r
1410EFI_STATUS\r
1411EFIAPI\r
1412Uhci2GetRootHubPortStatus (\r
1413 IN CONST EFI_USB2_HC_PROTOCOL *This,\r
1414 IN CONST UINT8 PortNumber,\r
1415 OUT EFI_USB_PORT_STATUS *PortStatus\r
1416 )\r
1417{\r
1418 USB_HC_DEV *Uhc;\r
1419\r
1420 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1421\r
1422 return UhciGetRootHubPortStatus (&Uhc->UsbHc, PortNumber, PortStatus);\r
1423}\r
1424\r
1425\r
1426/**\r
1427 Sets a feature for the specified root hub port according to UEFI 2.0 spec.\r
1428\r
1429 @param This A pointer to the EFI_USB2_HC_PROTOCOL.\r
1430 @param PortNumber Specifies the root hub port whose feature is\r
1431 requested to be set.\r
1432 @param PortFeature Indicates the feature selector associated with the\r
1433 feature set request.\r
1434\r
1435 @return EFI_SUCCESS : PortFeature was set for the root port\r
1436 @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
1437 @return EFI_DEVICE_ERROR : Can't read register\r
1438\r
1439**/\r
1440STATIC\r
1441EFI_STATUS\r
1442EFIAPI\r
1443Uhci2SetRootHubPortFeature (\r
1444 IN EFI_USB2_HC_PROTOCOL *This,\r
1445 IN UINT8 PortNumber,\r
1446 IN EFI_USB_PORT_FEATURE PortFeature\r
1447 )\r
1448{\r
1449 USB_HC_DEV *Uhc;\r
1450\r
1451 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1452\r
1453 return UhciSetRootHubPortFeature (&Uhc->UsbHc, PortNumber, PortFeature);\r
1454}\r
1455\r
1456\r
1457/**\r
1458 Clears a feature for the specified root hub port according to Uefi 2.0 spec.\r
1459\r
1460 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1461 @param PortNumber Specifies the root hub port whose feature is\r
1462 requested to be cleared.\r
1463 @param PortFeature Indicates the feature selector associated with the\r
1464 feature clear request.\r
1465\r
1466 @return EFI_SUCCESS : PortFeature was cleared for the USB root hub port\r
1467 @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
1468 @return EFI_DEVICE_ERROR : Can't read register\r
1469\r
1470**/\r
1471STATIC\r
1472EFI_STATUS\r
1473EFIAPI\r
1474Uhci2ClearRootHubPortFeature (\r
1475 IN EFI_USB2_HC_PROTOCOL *This,\r
1476 IN UINT8 PortNumber,\r
1477 IN EFI_USB_PORT_FEATURE PortFeature\r
1478 )\r
1479{\r
1480 USB_HC_DEV *Uhc;\r
1481\r
1482 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1483\r
1484 return UhciClearRootHubPortFeature (&Uhc->UsbHc, PortNumber, PortFeature);\r
1485}\r
1486\r
1487\r
1488/**\r
1489 Submits control transfer to a target USB device accroding to UEFI 2.0 spec..\r
1490\r
1491 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1492 DeviceAddress : Target device address\r
1493 DeviceSpeed : Device speed\r
1494 MaximumPacketLength : Maximum packet size of the target endpoint\r
1495 Request : USB device request to send\r
1496 TransferDirection : Data direction of the Data stage in control transfer\r
1497 Data : Data to transmit/receive in data stage\r
1498 DataLength : Length of the data\r
1499 TimeOut : Maximum time, in microseconds, for transfer to complete.\r
1500 TransferResult : Variable to receive the transfer result\r
1501\r
1502 @return EFI_SUCCESS : The control transfer was completed successfully.\r
1503 @return EFI_OUT_OF_RESOURCES : Failed due to lack of resource.\r
1504 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1505 @return EFI_TIMEOUT : Failed due to timeout.\r
1506 @return EFI_DEVICE_ERROR : Failed due to host controller or device error.\r
1507\r
1508**/\r
1509STATIC\r
1510EFI_STATUS\r
1511EFIAPI\r
1512Uhci2ControlTransfer (\r
1513 IN EFI_USB2_HC_PROTOCOL *This,\r
1514 IN UINT8 DeviceAddress,\r
1515 IN UINT8 DeviceSpeed,\r
1516 IN UINTN MaximumPacketLength,\r
1517 IN EFI_USB_DEVICE_REQUEST *Request,\r
1518 IN EFI_USB_DATA_DIRECTION TransferDirection,\r
1519 IN OUT VOID *Data,\r
1520 IN OUT UINTN *DataLength,\r
1521 IN UINTN TimeOut,\r
1522 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1523 OUT UINT32 *TransferResult\r
1524 )\r
1525{\r
1526 USB_HC_DEV *Uhc;\r
1527 BOOLEAN IsSlow;\r
1528\r
1529 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
c52fa98c 1530 IsSlow = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
913cb9dc 1531\r
1532 return UhciControlTransfer (\r
1533 &Uhc->UsbHc,\r
1534 DeviceAddress,\r
1535 IsSlow,\r
1536 (UINT8) MaximumPacketLength,\r
1537 Request,\r
1538 TransferDirection,\r
1539 Data,\r
1540 DataLength,\r
1541 TimeOut,\r
1542 TransferResult\r
1543 );\r
1544}\r
1545\r
1546\r
1547/**\r
1548 Submits bulk transfer to a bulk endpoint of a USB device\r
1549\r
1550 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1551 DeviceAddress : Target device address\r
1552 EndPointAddress : Endpoint number and direction\r
1553 DeviceSpeed : Device speed\r
1554 MaximumPacketLength : Maximum packet size of the target endpoint\r
1555 DataBuffersNumber : Number of data buffers prepared for the transfer.\r
1556 Data : Array of pointers to the buffers of data\r
1557 DataLength : On input, size of the data buffer, On output,\r
1558 actually transferred data size.\r
1559 DataToggle : On input, data toggle to use; On output, next data toggle\r
1560 Translator : A pointr to the transaction translator data.\r
1561 TimeOut : Maximum time out, in microseconds\r
1562 TransferResult : Variable to receive transfer result\r
1563\r
1564 @return EFI_SUCCESS : The bulk transfer was completed successfully.\r
1565 @return EFI_OUT_OF_RESOURCES : Failed due to lack of resource.\r
1566 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1567 @return EFI_TIMEOUT : Failed due to timeout.\r
1568 @return EFI_DEVICE_ERROR : Failed due to host controller or device error.\r
1569\r
1570**/\r
1571STATIC\r
1572EFI_STATUS\r
1573EFIAPI\r
1574Uhci2BulkTransfer (\r
1575 IN EFI_USB2_HC_PROTOCOL *This,\r
1576 IN UINT8 DeviceAddress,\r
1577 IN UINT8 EndPointAddress,\r
1578 IN UINT8 DeviceSpeed,\r
1579 IN UINTN MaximumPacketLength,\r
1580 IN UINT8 DataBuffersNumber,\r
1581 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
1582 IN OUT UINTN *DataLength,\r
1583 IN OUT UINT8 *DataToggle,\r
1584 IN UINTN TimeOut,\r
1585 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1586 OUT UINT32 *TransferResult\r
1587 )\r
1588{\r
1589 USB_HC_DEV *Uhc;\r
1590\r
1591 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1592\r
1593 if (Data == NULL || DeviceSpeed == EFI_USB_SPEED_LOW) {\r
1594 return EFI_INVALID_PARAMETER;\r
1595 }\r
1596\r
1597 //\r
1598 // For full-speed bulk transfers only the data pointed by Data[0] shall be used\r
1599 //\r
1600 return UhciBulkTransfer (\r
1601 &Uhc->UsbHc,\r
1602 DeviceAddress,\r
1603 EndPointAddress,\r
1604 (UINT8) MaximumPacketLength,\r
1605 *Data,\r
1606 DataLength,\r
1607 DataToggle,\r
1608 TimeOut,\r
1609 TransferResult\r
1610 );\r
1611}\r
1612\r
1613\r
1614/**\r
1615 Submits an asynchronous interrupt transfer to an\r
1616 interrupt endpoint of a USB device according to UEFI 2.0 spec.\r
1617\r
1618 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1619 DeviceAddress : Target device address\r
1620 EndPointAddress : Endpoint number and direction\r
1621 DeviceSpeed : Device speed\r
1622 MaximumPacketLength : Maximum packet size of the target endpoint\r
1623 IsNewTransfer : If TRUE, submit a new transfer, if FALSE cancel old transfer\r
1624 DataToggle : On input, data toggle to use; On output, next data toggle\r
1625 PollingInterval : Interrupt poll rate in milliseconds\r
1626 DataLength : On input, size of the data buffer, On output,\r
1627 actually transferred data size.\r
1628 Translator : A pointr to the transaction translator data.\r
1629 CallBackFunction : Function to call periodically\r
1630 Context : User context\r
1631\r
1632 @return EFI_SUCCESS : Transfer was submitted\r
1633 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1634 @return EFI_OUT_OF_RESOURCES : Failed due to a lack of resources.\r
1635 @return EFI_DEVICE_ERROR : Can't read register\r
1636\r
1637**/\r
1638STATIC\r
1639EFI_STATUS\r
1640EFIAPI\r
1641Uhci2AsyncInterruptTransfer (\r
1642 IN EFI_USB2_HC_PROTOCOL *This,\r
1643 IN UINT8 DeviceAddress,\r
1644 IN UINT8 EndPointAddress,\r
1645 IN UINT8 DeviceSpeed,\r
1646 IN UINTN MaximumPacketLength,\r
1647 IN BOOLEAN IsNewTransfer,\r
1648 IN OUT UINT8 *DataToggle,\r
1649 IN UINTN PollingInterval,\r
1650 IN UINTN DataLength,\r
1651 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1652 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,\r
1653 IN VOID *Context\r
1654 )\r
1655{\r
1656 USB_HC_DEV *Uhc;\r
1657 BOOLEAN IsSlow;\r
1658\r
1659 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
c52fa98c 1660 IsSlow = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
913cb9dc 1661\r
1662 return UhciAsyncInterruptTransfer (\r
1663 &Uhc->UsbHc,\r
1664 DeviceAddress,\r
1665 EndPointAddress,\r
1666 IsSlow,\r
1667 (UINT8) MaximumPacketLength,\r
1668 IsNewTransfer,\r
1669 DataToggle,\r
1670 PollingInterval,\r
1671 DataLength,\r
1672 CallBackFunction,\r
1673 Context\r
1674 );\r
1675}\r
1676\r
1677\r
1678/**\r
1679 Submits synchronous interrupt transfer to an interrupt endpoint\r
1680 of a USB device according to UEFI 2.0 spec.\r
1681\r
1682 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1683 DeviceAddress : Target device address\r
1684 EndPointAddress : Endpoint number and direction\r
1685 DeviceSpeed : Device speed\r
1686 MaximumPacketLength : Maximum packet size of the target endpoint\r
1687 DataBuffersNumber : Number of data buffers prepared for the transfer.\r
1688 Data : Array of pointers to the buffers of data\r
1689 DataLength : On input, size of the data buffer, On output,\r
1690 actually transferred data size.\r
1691 DataToggle : On input, data toggle to use; On output, next data toggle\r
1692 TimeOut : Maximum time out, in microseconds\r
1693 Translator : A pointr to the transaction translator data.\r
1694 TransferResult : Variable to receive transfer result\r
1695\r
1696 @return EFI_SUCCESS : The transfer was completed successfully.\r
1697 @return EFI_OUT_OF_RESOURCES : Failed due to lack of resource.\r
1698 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1699 @return EFI_TIMEOUT : Failed due to timeout.\r
1700 @return EFI_DEVICE_ERROR : Failed due to host controller or device error.\r
1701\r
1702**/\r
1703STATIC\r
1704EFI_STATUS\r
1705EFIAPI\r
1706Uhci2SyncInterruptTransfer (\r
1707 IN EFI_USB2_HC_PROTOCOL *This,\r
1708 IN UINT8 DeviceAddress,\r
1709 IN UINT8 EndPointAddress,\r
1710 IN UINT8 DeviceSpeed,\r
1711 IN UINTN MaximumPacketLength,\r
1712 IN OUT VOID *Data,\r
1713 IN OUT UINTN *DataLength,\r
1714 IN OUT UINT8 *DataToggle,\r
1715 IN UINTN TimeOut,\r
1716 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1717 OUT UINT32 *TransferResult\r
1718 )\r
1719{\r
1720 USB_HC_DEV *Uhc;\r
1721 BOOLEAN IsSlow;\r
1722\r
1723 if (DeviceSpeed == EFI_USB_SPEED_HIGH) {\r
1724 return EFI_INVALID_PARAMETER;\r
1725 }\r
1726\r
1727 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
c52fa98c 1728 IsSlow = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
913cb9dc 1729\r
1730 return UhciSyncInterruptTransfer (\r
1731 &Uhc->UsbHc,\r
1732 DeviceAddress,\r
1733 EndPointAddress,\r
1734 IsSlow,\r
1735 (UINT8) MaximumPacketLength,\r
1736 Data,\r
1737 DataLength,\r
1738 DataToggle,\r
1739 TimeOut,\r
1740 TransferResult\r
1741 );\r
1742}\r
1743\r
1744\r
1745/**\r
1746 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
1747\r
1748 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1749 DeviceAddress : Target device address\r
1750 EndPointAddress : Endpoint number and direction\r
1751 DeviceSpeed : Device speed\r
1752 MaximumPacketLength : Maximum packet size of the target endpoint\r
1753 DataBuffersNumber : Number of data buffers prepared for the transfer.\r
1754 Data : Array of pointers to the buffers of data\r
1755 DataLength : On input, size of the data buffer, On output,\r
1756 actually transferred data size.\r
1757 Translator : A pointr to the transaction translator data.\r
1758 TransferResult : Variable to receive transfer result\r
1759\r
1760 @return EFI_UNSUPPORTED\r
1761\r
1762**/\r
1763STATIC\r
1764EFI_STATUS\r
1765EFIAPI\r
1766Uhci2IsochronousTransfer (\r
1767 IN EFI_USB2_HC_PROTOCOL *This,\r
1768 IN UINT8 DeviceAddress,\r
1769 IN UINT8 EndPointAddress,\r
1770 IN UINT8 DeviceSpeed,\r
1771 IN UINTN MaximumPacketLength,\r
1772 IN UINT8 DataBuffersNumber,\r
1773 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1774 IN UINTN DataLength,\r
1775 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1776 OUT UINT32 *TransferResult\r
1777 )\r
1778{\r
1779 return EFI_UNSUPPORTED;\r
1780}\r
1781\r
1782\r
1783/**\r
1784 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
1785\r
1786 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1787 DeviceAddress : Target device address\r
1788 EndPointAddress : Endpoint number and direction\r
1789 DeviceSpeed : Device speed\r
1790 MaximumPacketLength : Maximum packet size of the target endpoint\r
1791 DataBuffersNumber : Number of data buffers prepared for the transfer.\r
1792 Data : Array of pointers to the buffers of data\r
1793 Translator : A pointr to the transaction translator data.\r
1794 IsochronousCallBack : Function to call when the transfer complete\r
1795 Context : Pass to the call back function as parameter\r
1796\r
1797 @return EFI_UNSUPPORTED\r
1798\r
1799**/\r
1800STATIC\r
1801EFI_STATUS\r
1802EFIAPI\r
1803Uhci2AsyncIsochronousTransfer (\r
1804 IN EFI_USB2_HC_PROTOCOL *This,\r
1805 IN UINT8 DeviceAddress,\r
1806 IN UINT8 EndPointAddress,\r
1807 IN UINT8 DeviceSpeed,\r
1808 IN UINTN MaximumPacketLength,\r
1809 IN UINT8 DataBuffersNumber,\r
1810 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1811 IN UINTN DataLength,\r
1812 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1813 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
1814 IN VOID *Context\r
1815 )\r
1816{\r
1817 return EFI_UNSUPPORTED;\r
1818}\r
1819\r
913cb9dc 1820EFI_STATUS\r
1821EFIAPI\r
1822UhciDriverEntryPoint (\r
1823 IN EFI_HANDLE ImageHandle,\r
1824 IN EFI_SYSTEM_TABLE *SystemTable\r
1825 )\r
1826/*++\r
1827\r
1828 Routine Description:\r
1829\r
1830 Entry point for EFI drivers.\r
1831\r
1832 Arguments:\r
1833\r
1834 ImageHandle - EFI_HANDLE\r
1835 SystemTable - EFI_SYSTEM_TABLE\r
1836\r
1837 Returns:\r
1838\r
1839 EFI_SUCCESS : Driver is successfully loaded\r
1840 Others : Failed\r
1841\r
1842--*/\r
1843{\r
f527bce3 1844 return EfiLibInstallDriverBindingComponentName2 (\r
913cb9dc 1845 ImageHandle,\r
1846 SystemTable,\r
1847 &gUhciDriverBinding,\r
1848 ImageHandle,\r
1849 &gUhciComponentName,\r
f527bce3 1850 &gUhciComponentName2\r
913cb9dc 1851 );\r
1852}\r
1853\r
1854\r
1855/**\r
1856 Test to see if this driver supports ControllerHandle. Any\r
1857 ControllerHandle that has UsbHcProtocol installed will be supported.\r
1858\r
1859 @param This Protocol instance pointer.\r
1860 @param Controller Handle of device to test\r
1861 @param RemainingDevicePath Not used\r
1862\r
1863 @return EFI_SUCCESS : This driver supports this device.\r
1864 @return EFI_UNSUPPORTED : This driver does not support this device.\r
1865\r
1866**/\r
1867EFI_STATUS\r
1868EFIAPI\r
1869UhciDriverBindingSupported (\r
1870 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1871 IN EFI_HANDLE Controller,\r
1872 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1873 )\r
1874{\r
1875 EFI_STATUS OpenStatus;\r
1876 EFI_STATUS Status;\r
1877 EFI_PCI_IO_PROTOCOL *PciIo;\r
1878 USB_CLASSC UsbClassCReg;\r
1879\r
1880 //\r
1881 // Test whether there is PCI IO Protocol attached on the controller handle.\r
1882 //\r
1883 OpenStatus = gBS->OpenProtocol (\r
1884 Controller,\r
1885 &gEfiPciIoProtocolGuid,\r
c52fa98c 1886 (VOID **) &PciIo,\r
913cb9dc 1887 This->DriverBindingHandle,\r
1888 Controller,\r
1889 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1890 );\r
1891\r
1892 if (EFI_ERROR (OpenStatus)) {\r
1893 return OpenStatus;\r
1894 }\r
1895\r
1896 Status = PciIo->Pci.Read (\r
1897 PciIo,\r
1898 EfiPciIoWidthUint8,\r
1899 CLASSC_OFFSET,\r
1900 sizeof (USB_CLASSC) / sizeof (UINT8),\r
1901 &UsbClassCReg\r
1902 );\r
1903\r
1904 if (EFI_ERROR (Status)) {\r
1905 Status = EFI_UNSUPPORTED;\r
1906 goto ON_EXIT;\r
1907 }\r
1908\r
1909 //\r
1910 // Test whether the controller belongs to UHCI type\r
1911 //\r
1912 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
1913 (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
1914 (UsbClassCReg.PI != PCI_CLASSC_PI_UHCI)\r
1915 ) {\r
1916\r
1917 Status = EFI_UNSUPPORTED;\r
1918 }\r
1919\r
1920ON_EXIT:\r
1921 gBS->CloseProtocol (\r
1922 Controller,\r
1923 &gEfiPciIoProtocolGuid,\r
1924 This->DriverBindingHandle,\r
1925 Controller\r
1926 );\r
1927\r
1928 return Status;\r
1929\r
1930}\r
1931\r
1932\r
1933/**\r
1934 Allocate and initialize the empty UHCI device\r
1935\r
1936 @param PciIo The PCIIO to use\r
1937\r
1938 @return Allocated UHCI device\r
1939\r
1940**/\r
1941STATIC\r
1942USB_HC_DEV *\r
1943UhciAllocateDev (\r
68246fa8 1944 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1945 IN UINT64 OriginalPciAttributes\r
913cb9dc 1946 )\r
1947{\r
1948 USB_HC_DEV *Uhc;\r
1949 EFI_STATUS Status;\r
1950\r
1951 Uhc = AllocateZeroPool (sizeof (USB_HC_DEV));\r
1952\r
1953 if (Uhc == NULL) {\r
1954 return NULL;\r
1955 }\r
1956\r
1957 //\r
1958 // This driver supports both USB_HC_PROTOCOL and USB2_HC_PROTOCOL.\r
1959 // USB_HC_PROTOCOL is for EFI 1.1 backward compability.\r
1960 //\r
1961 Uhc->Signature = USB_HC_DEV_SIGNATURE;\r
1962 Uhc->UsbHc.Reset = UhciReset;\r
1963 Uhc->UsbHc.GetState = UhciGetState;\r
1964 Uhc->UsbHc.SetState = UhciSetState;\r
1965 Uhc->UsbHc.ControlTransfer = UhciControlTransfer;\r
1966 Uhc->UsbHc.BulkTransfer = UhciBulkTransfer;\r
1967 Uhc->UsbHc.AsyncInterruptTransfer = UhciAsyncInterruptTransfer;\r
1968 Uhc->UsbHc.SyncInterruptTransfer = UhciSyncInterruptTransfer;\r
1969 Uhc->UsbHc.IsochronousTransfer = UhciIsochronousTransfer;\r
1970 Uhc->UsbHc.AsyncIsochronousTransfer = UhciAsyncIsochronousTransfer;\r
1971 Uhc->UsbHc.GetRootHubPortNumber = UhciGetRootHubPortNumber;\r
1972 Uhc->UsbHc.GetRootHubPortStatus = UhciGetRootHubPortStatus;\r
1973 Uhc->UsbHc.SetRootHubPortFeature = UhciSetRootHubPortFeature;\r
1974 Uhc->UsbHc.ClearRootHubPortFeature = UhciClearRootHubPortFeature;\r
1975 Uhc->UsbHc.MajorRevision = 0x1;\r
1976 Uhc->UsbHc.MinorRevision = 0x1;\r
1977\r
1978 Uhc->Usb2Hc.GetCapability = Uhci2GetCapability;\r
1979 Uhc->Usb2Hc.Reset = Uhci2Reset;\r
1980 Uhc->Usb2Hc.GetState = Uhci2GetState;\r
1981 Uhc->Usb2Hc.SetState = Uhci2SetState;\r
1982 Uhc->Usb2Hc.ControlTransfer = Uhci2ControlTransfer;\r
1983 Uhc->Usb2Hc.BulkTransfer = Uhci2BulkTransfer;\r
1984 Uhc->Usb2Hc.AsyncInterruptTransfer = Uhci2AsyncInterruptTransfer;\r
1985 Uhc->Usb2Hc.SyncInterruptTransfer = Uhci2SyncInterruptTransfer;\r
1986 Uhc->Usb2Hc.IsochronousTransfer = Uhci2IsochronousTransfer;\r
1987 Uhc->Usb2Hc.AsyncIsochronousTransfer = Uhci2AsyncIsochronousTransfer;\r
1988 Uhc->Usb2Hc.GetRootHubPortStatus = Uhci2GetRootHubPortStatus;\r
1989 Uhc->Usb2Hc.SetRootHubPortFeature = Uhci2SetRootHubPortFeature;\r
1990 Uhc->Usb2Hc.ClearRootHubPortFeature = Uhci2ClearRootHubPortFeature;\r
1991 Uhc->Usb2Hc.MajorRevision = 0x1;\r
1992 Uhc->Usb2Hc.MinorRevision = 0x1;\r
1993\r
68246fa8 1994 Uhc->PciIo = PciIo;\r
1995 Uhc->OriginalPciAttributes = OriginalPciAttributes;\r
1996 Uhc->MemPool = UsbHcInitMemPool (PciIo, TRUE, 0);\r
913cb9dc 1997\r
1998 if (Uhc->MemPool == NULL) {\r
1999 Status = EFI_OUT_OF_RESOURCES;\r
2000 goto ON_ERROR;\r
2001 }\r
2002\r
2003 InitializeListHead (&Uhc->AsyncIntList);\r
2004\r
2005 Status = gBS->CreateEvent (\r
2006 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
2007 TPL_CALLBACK,\r
2008 UhciMonitorAsyncReqList,\r
2009 Uhc,\r
2010 &Uhc->AsyncIntMonitor\r
2011 );\r
2012\r
2013 if (EFI_ERROR (Status)) {\r
2014 UsbHcFreeMemPool (Uhc->MemPool);\r
2015 goto ON_ERROR;\r
2016 }\r
2017\r
2018 return Uhc;\r
2019\r
2020ON_ERROR:\r
2021 gBS->FreePool (Uhc);\r
2022 return NULL;\r
2023}\r
2024\r
2025\r
2026/**\r
2027 Free the UHCI device and release its associated resources\r
2028\r
2029 @param Uhc The UHCI device to release\r
2030\r
2031 @return None\r
2032\r
2033**/\r
2034STATIC\r
2035VOID\r
2036UhciFreeDev (\r
2037 IN USB_HC_DEV *Uhc\r
2038 )\r
2039{\r
2040 if (Uhc->AsyncIntMonitor != NULL) {\r
2041 gBS->CloseEvent (Uhc->AsyncIntMonitor);\r
2042 }\r
2043\r
2044 if (Uhc->MemPool != NULL) {\r
2045 UsbHcFreeMemPool (Uhc->MemPool);\r
2046 }\r
2047\r
2048 if (Uhc->CtrlNameTable) {\r
2049 FreeUnicodeStringTable (Uhc->CtrlNameTable);\r
2050 }\r
2051\r
2052 gBS->FreePool (Uhc);\r
2053}\r
2054\r
2055\r
2056/**\r
2057 Uninstall all Uhci Interface\r
2058\r
2059 @param Controller Controller handle\r
2060 @param This Protocol instance pointer.\r
2061\r
2062 @return VOID\r
2063\r
2064**/\r
2065STATIC\r
2066VOID\r
2067UhciCleanDevUp (\r
2068 IN EFI_HANDLE Controller,\r
2069 IN EFI_USB_HC_PROTOCOL *This\r
2070 )\r
2071{\r
2072 USB_HC_DEV *Uhc;\r
2073\r
2074 //\r
2075 // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller\r
2076 //\r
2077 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
41e8ff27 2078 UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
913cb9dc 2079\r
2080 gBS->UninstallProtocolInterface (\r
2081 Controller,\r
2082 &gEfiUsbHcProtocolGuid,\r
2083 &Uhc->UsbHc\r
2084 );\r
2085\r
2086 gBS->UninstallProtocolInterface (\r
2087 Controller,\r
2088 &gEfiUsb2HcProtocolGuid,\r
2089 &Uhc->Usb2Hc\r
2090 );\r
2091\r
2092 UhciFreeAllAsyncReq (Uhc);\r
2093 UhciDestoryFrameList (Uhc);\r
68246fa8 2094\r
2095 //\r
2096 // Restore original PCI attributes\r
2097 //\r
913cb9dc 2098 Uhc->PciIo->Attributes (\r
68246fa8 2099 Uhc->PciIo,\r
2100 EfiPciIoAttributeOperationSet,\r
2101 Uhc->OriginalPciAttributes,\r
2102 NULL\r
2103 );\r
913cb9dc 2104\r
2105 UhciFreeDev (Uhc);\r
2106}\r
2107\r
2108\r
2109/**\r
2110 Starting the Usb UHCI Driver\r
2111\r
2112 @param This Protocol instance pointer.\r
2113 @param Controller Handle of device to test\r
2114 @param RemainingDevicePath Not used\r
2115\r
2116 @retval EFI_SUCCESS This driver supports this device.\r
2117 @retval EFI_UNSUPPORTED This driver does not support this device.\r
2118 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error\r
2119 EFI_OUT_OF_RESOURCES- Failed due to resource\r
2120 shortage\r
2121\r
2122**/\r
2123EFI_STATUS\r
2124EFIAPI\r
2125UhciDriverBindingStart (\r
2126 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
2127 IN EFI_HANDLE Controller,\r
2128 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
2129 )\r
2130{\r
2131 EFI_STATUS Status;\r
2132 EFI_PCI_IO_PROTOCOL *PciIo;\r
2133 USB_HC_DEV *Uhc;\r
96f6af14 2134 UINT64 Supports;\r
68246fa8 2135 UINT64 OriginalPciAttributes;\r
6a6d955c 2136 BOOLEAN PciAttributesSaved;\r
913cb9dc 2137\r
2138 //\r
2139 // Open PCIIO, then enable the EHC device and turn off emulation\r
2140 //\r
2141 Uhc = NULL;\r
2142 Status = gBS->OpenProtocol (\r
2143 Controller,\r
2144 &gEfiPciIoProtocolGuid,\r
c52fa98c 2145 (VOID **) &PciIo,\r
913cb9dc 2146 This->DriverBindingHandle,\r
2147 Controller,\r
2148 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2149 );\r
2150\r
2151 if (EFI_ERROR (Status)) {\r
2152 return Status;\r
2153 }\r
2154\r
6a6d955c 2155 PciAttributesSaved = FALSE;\r
68246fa8 2156 //\r
2157 // Save original PCI attributes\r
2158 //\r
2159 Status = PciIo->Attributes (\r
2160 PciIo,\r
2161 EfiPciIoAttributeOperationGet,\r
2162 0,\r
2163 &OriginalPciAttributes\r
2164 );\r
2165\r
2166 if (EFI_ERROR (Status)) {\r
6a6d955c 2167 goto CLOSE_PCIIO;\r
68246fa8 2168 }\r
6a6d955c 2169 PciAttributesSaved = TRUE;\r
68246fa8 2170\r
913cb9dc 2171 UhciTurnOffUsbEmulation (PciIo);\r
2172\r
2173 Status = PciIo->Attributes (\r
2174 PciIo,\r
96f6af14
LG
2175 EfiPciIoAttributeOperationSupported,\r
2176 0,\r
2177 &Supports\r
913cb9dc 2178 );\r
96f6af14
LG
2179 if (!EFI_ERROR (Status)) {\r
2180 Supports &= EFI_PCI_DEVICE_ENABLE;\r
2181 Status = PciIo->Attributes (\r
2182 PciIo,\r
2183 EfiPciIoAttributeOperationEnable,\r
2184 Supports,\r
2185 NULL\r
2186 );\r
2187 }\r
913cb9dc 2188\r
2189 if (EFI_ERROR (Status)) {\r
2190 goto CLOSE_PCIIO;\r
2191 }\r
2192\r
68246fa8 2193 Uhc = UhciAllocateDev (PciIo, OriginalPciAttributes);\r
913cb9dc 2194\r
2195 if (Uhc == NULL) {\r
2196 Status = EFI_OUT_OF_RESOURCES;\r
2197 goto CLOSE_PCIIO;\r
2198 }\r
2199\r
2200 //\r
2201 // Allocate and Init Host Controller's Frame List Entry\r
2202 //\r
2203 Status = UhciInitFrameList (Uhc);\r
2204\r
2205 if (EFI_ERROR (Status)) {\r
2206 Status = EFI_OUT_OF_RESOURCES;\r
2207 goto FREE_UHC;\r
2208 }\r
2209\r
2210 Status = gBS->SetTimer (\r
2211 Uhc->AsyncIntMonitor,\r
2212 TimerPeriodic,\r
41e8ff27 2213 UHC_ASYNC_POLL_INTERVAL\r
913cb9dc 2214 );\r
2215\r
2216 if (EFI_ERROR (Status)) {\r
2217 goto FREE_UHC;\r
2218 }\r
2219\r
2220 //\r
2221 // Install both USB_HC_PROTOCOL and USB2_HC_PROTOCOL\r
2222 //\r
2223 Status = gBS->InstallMultipleProtocolInterfaces (\r
2224 &Controller,\r
2225 &gEfiUsbHcProtocolGuid,\r
2226 &Uhc->UsbHc,\r
2227 &gEfiUsb2HcProtocolGuid,\r
2228 &Uhc->Usb2Hc,\r
2229 NULL\r
2230 );\r
2231\r
2232 if (EFI_ERROR (Status)) {\r
2233 goto FREE_UHC;\r
2234 }\r
2235\r
2236 //\r
2237 // Install the component name protocol\r
2238 //\r
2239 Uhc->CtrlNameTable = NULL;\r
2240\r
f527bce3 2241 AddUnicodeString2 (\r
913cb9dc 2242 "eng",\r
2243 gUhciComponentName.SupportedLanguages,\r
2244 &Uhc->CtrlNameTable,\r
f527bce3 2245 L"Usb Universal Host Controller",\r
2246 TRUE\r
913cb9dc 2247 );\r
f527bce3 2248 AddUnicodeString2 (\r
2249 "en",\r
2250 gUhciComponentName2.SupportedLanguages,\r
2251 &Uhc->CtrlNameTable,\r
2252 L"Usb Universal Host Controller",\r
2253 FALSE\r
2254 );\r
2255\r
913cb9dc 2256\r
2257 //\r
2258 // Start the UHCI hardware, also set its reclamation point to 64 bytes\r
2259 //\r
2260 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, USBCMD_RS | USBCMD_MAXP);\r
2261\r
2262 return EFI_SUCCESS;\r
2263\r
2264FREE_UHC:\r
2265 UhciFreeDev (Uhc);\r
2266\r
2267CLOSE_PCIIO:\r
6a6d955c 2268 if (PciAttributesSaved == TRUE) {\r
2269 //\r
2270 // Restore original PCI attributes\r
2271 //\r
2272 PciIo->Attributes (\r
2273 PciIo,\r
2274 EfiPciIoAttributeOperationSet,\r
2275 OriginalPciAttributes,\r
2276 NULL\r
2277 );\r
2278 }\r
68246fa8 2279\r
913cb9dc 2280 gBS->CloseProtocol (\r
2281 Controller,\r
2282 &gEfiPciIoProtocolGuid,\r
2283 This->DriverBindingHandle,\r
2284 Controller\r
2285 );\r
2286\r
2287 return Status;\r
2288}\r
2289\r
2290\r
2291/**\r
2292 Stop this driver on ControllerHandle. Support stoping any child handles\r
2293 created by this driver.\r
2294\r
2295 @param This Protocol instance pointer.\r
2296 @param Controller Handle of device to stop driver on\r
2297 @param NumberOfChildren Number of Children in the ChildHandleBuffer\r
2298 @param ChildHandleBuffer List of handles for the children we need to stop.\r
2299\r
2300 @return EFI_SUCCESS\r
2301 @return others\r
2302\r
2303**/\r
2304EFI_STATUS\r
2305EFIAPI\r
2306UhciDriverBindingStop (\r
2307 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
2308 IN EFI_HANDLE Controller,\r
2309 IN UINTN NumberOfChildren,\r
2310 IN EFI_HANDLE *ChildHandleBuffer\r
2311 )\r
2312{\r
2313 EFI_USB_HC_PROTOCOL *UsbHc;\r
2314 EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
2315 EFI_STATUS Status;\r
2316\r
2317 Status = gBS->OpenProtocol (\r
2318 Controller,\r
2319 &gEfiUsbHcProtocolGuid,\r
c52fa98c 2320 (VOID **) &UsbHc,\r
913cb9dc 2321 This->DriverBindingHandle,\r
2322 Controller,\r
2323 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2324 );\r
2325 //\r
2326 // Test whether the Controller handler passed in is a valid\r
2327 // Usb controller handle that should be supported, if not,\r
2328 // return the error status directly\r
2329 //\r
2330 if (EFI_ERROR (Status)) {\r
2331 return Status;\r
2332 }\r
2333\r
2334 Status = gBS->OpenProtocol (\r
2335 Controller,\r
2336 &gEfiUsb2HcProtocolGuid,\r
c52fa98c 2337 (VOID **) &Usb2Hc,\r
913cb9dc 2338 This->DriverBindingHandle,\r
2339 Controller,\r
2340 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2341 );\r
2342\r
2343 //\r
2344 // Test whether the Controller handler passed in is a valid\r
2345 // Usb controller handle that should be supported, if not,\r
2346 // return the error status directly\r
2347 //\r
2348 if (EFI_ERROR (Status)) {\r
2349 return Status;\r
2350 }\r
2351\r
2352 UhciCleanDevUp (Controller, UsbHc);\r
2353\r
2354 gBS->CloseProtocol (\r
2355 Controller,\r
2356 &gEfiPciIoProtocolGuid,\r
2357 This->DriverBindingHandle,\r
2358 Controller\r
2359 );\r
2360\r
2361 return EFI_SUCCESS;\r
2362}\r
2363\r
2364EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding = {\r
2365 UhciDriverBindingSupported,\r
2366 UhciDriverBindingStart,\r
2367 UhciDriverBindingStop,\r
2368 0x20,\r
2369 NULL,\r
2370 NULL\r
2371};\r