Update to support to produce Component Name and & Component Name 2 protocol based...
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / EhciDxe / Ehci.c
CommitLineData
913cb9dc 1/** @file\r
2\r
3Copyright (c) 2006 - 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 Ehci.c\r
15\r
16Abstract:\r
17\r
18\r
19Revision History\r
20\r
21**/\r
22\r
23\r
24#include "Ehci.h"\r
25\r
26//\r
27// Two arrays used to translate the EHCI port state (change)\r
28// to the UEFI protocol's port state (change).\r
29//\r
30USB_PORT_STATE_MAP mUsbPortStateMap[] = {\r
31 {PORTSC_CONN, USB_PORT_STAT_CONNECTION},\r
32 {PORTSC_ENABLED, USB_PORT_STAT_ENABLE},\r
33 {PORTSC_SUSPEND, USB_PORT_STAT_SUSPEND},\r
34 {PORTSC_OVERCUR, USB_PORT_STAT_OVERCURRENT},\r
35 {PORTSC_RESET, USB_PORT_STAT_RESET},\r
36 {PORTSC_POWER, USB_PORT_STAT_POWER},\r
37 {PORTSC_OWNER, USB_PORT_STAT_OWNER}\r
38};\r
39\r
40USB_PORT_STATE_MAP mUsbPortChangeMap[] = {\r
41 {PORTSC_CONN_CHANGE, USB_PORT_STAT_C_CONNECTION},\r
42 {PORTSC_ENABLE_CHANGE, USB_PORT_STAT_C_ENABLE},\r
43 {PORTSC_OVERCUR_CHANGE, USB_PORT_STAT_C_OVERCURRENT}\r
44};\r
45\r
46\r
47/**\r
48 Retrieves the capablility of root hub ports.\r
49\r
50 @param This This EFI_USB_HC_PROTOCOL instance.\r
51 @param MaxSpeed Max speed supported by the controller\r
52 @param PortNumber Number of the root hub ports.\r
53 @param Is64BitCapable Whether the controller supports 64-bit memory\r
54 addressing.\r
55\r
56 @return EFI_SUCCESS : host controller capability were retrieved successfully.\r
57 @return EFI_INVALID_PARAMETER : Either of the three capability pointer is NULL\r
58\r
59**/\r
60STATIC\r
61EFI_STATUS\r
62EFIAPI\r
63EhcGetCapability (\r
64 IN EFI_USB2_HC_PROTOCOL *This,\r
65 OUT UINT8 *MaxSpeed,\r
66 OUT UINT8 *PortNumber,\r
67 OUT UINT8 *Is64BitCapable\r
68 )\r
69{\r
70 USB2_HC_DEV *Ehc;\r
71 EFI_TPL OldTpl;\r
72\r
73 if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {\r
74 return EFI_INVALID_PARAMETER;\r
75 }\r
76\r
77 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
78 Ehc = EHC_FROM_THIS (This);\r
79\r
80 *MaxSpeed = EFI_USB_SPEED_HIGH;\r
81 *PortNumber = (UINT8) (Ehc->HcStructParams & HCSP_NPORTS);\r
82 *Is64BitCapable = (UINT8) (Ehc->HcCapParams & HCCP_64BIT);\r
83\r
84 EHC_DEBUG (("EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));\r
85\r
86 gBS->RestoreTPL (OldTpl);\r
87 return EFI_SUCCESS;\r
88}\r
89\r
90\r
91/**\r
92 Provides software reset for the USB host controller.\r
93\r
94 @param This This EFI_USB2_HC_PROTOCOL instance.\r
95 @param Attributes A bit mask of the reset operation to perform.\r
96\r
97 @return EFI_SUCCESS : The reset operation succeeded.\r
98 @return EFI_INVALID_PARAMETER : Attributes is not valid.\r
99 @return EFI_UNSUPPOURTED : The type of reset specified by Attributes is\r
100 @return not currently supported by the host controller.\r
101 @return EFI_DEVICE_ERROR : Host controller isn't halted to reset.\r
102\r
103**/\r
104STATIC\r
105EFI_STATUS\r
106EFIAPI\r
107EhcReset (\r
108 IN EFI_USB2_HC_PROTOCOL *This,\r
109 IN UINT16 Attributes\r
110 )\r
111{\r
112 USB2_HC_DEV *Ehc;\r
113 EFI_TPL OldTpl;\r
114 EFI_STATUS Status;\r
115\r
116 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
117 Ehc = EHC_FROM_THIS (This);\r
118\r
119 switch (Attributes) {\r
120 case EFI_USB_HC_RESET_GLOBAL:\r
121 //\r
122 // Flow through, same behavior as Host Controller Reset\r
123 //\r
124 case EFI_USB_HC_RESET_HOST_CONTROLLER:\r
125 //\r
126 // Host Controller must be Halt when Reset it\r
127 //\r
128 if (!EhcIsHalt (Ehc)) {\r
129 Status = EhcHaltHC (Ehc, EHC_GENERIC_TIME);\r
130\r
131 if (EFI_ERROR (Status)) {\r
132 Status = EFI_DEVICE_ERROR;\r
133 goto ON_EXIT;\r
134 }\r
135 }\r
136\r
137 //\r
138 // Clean up the asynchronous transfers, currently only\r
139 // interrupt supports asynchronous operation.\r
140 //\r
141 EhciDelAllAsyncIntTransfers (Ehc);\r
142 EhcAckAllInterrupt (Ehc);\r
143 EhcFreeSched (Ehc);\r
144\r
145 Status = EhcResetHC (Ehc, EHC_STALL_1_SECOND);\r
146\r
147 if (EFI_ERROR (Status)) {\r
148 goto ON_EXIT;\r
149 }\r
150\r
151 Status = EhcInitHC (Ehc);\r
152 break;\r
153\r
154 case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:\r
155 case EFI_USB_HC_RESET_HOST_WITH_DEBUG:\r
156 Status = EFI_UNSUPPORTED;\r
157 break;\r
158\r
159 default:\r
160 Status = EFI_INVALID_PARAMETER;\r
161 }\r
162\r
163ON_EXIT:\r
164 EHC_DEBUG (("EhcReset: exit status %r\n", Status));\r
165 gBS->RestoreTPL (OldTpl);\r
166 return Status;\r
167}\r
168\r
169\r
170/**\r
171 Retrieve the current state of the USB host controller.\r
172\r
173 @param This This EFI_USB2_HC_PROTOCOL instance.\r
174 @param State Variable to return the current host controller\r
175 state.\r
176\r
177 @return EFI_SUCCESS : Host controller state was returned in State.\r
178 @return EFI_INVALID_PARAMETER : State is NULL.\r
179 @return EFI_DEVICE_ERROR : An error was encountered while attempting to\r
180 @return retrieve the host controller's current state.\r
181\r
182**/\r
183STATIC\r
184EFI_STATUS\r
185EFIAPI\r
186EhcGetState (\r
187 IN CONST EFI_USB2_HC_PROTOCOL *This,\r
188 OUT EFI_USB_HC_STATE *State\r
189 )\r
190{\r
191 EFI_TPL OldTpl;\r
192 USB2_HC_DEV *Ehc;\r
193\r
194 if (State == NULL) {\r
195 return EFI_INVALID_PARAMETER;\r
196 }\r
197\r
198 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
199 Ehc = EHC_FROM_THIS (This);\r
200\r
201 if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {\r
202 *State = EfiUsbHcStateHalt;\r
203 } else {\r
204 *State = EfiUsbHcStateOperational;\r
205 }\r
206\r
207 gBS->RestoreTPL (OldTpl);\r
208\r
209 EHC_DEBUG (("EhcGetState: current state %d\n", *State));\r
210 return EFI_SUCCESS;\r
211}\r
212\r
213\r
214/**\r
215 Sets the USB host controller to a specific state.\r
216\r
217 @param This This EFI_USB2_HC_PROTOCOL instance.\r
218 @param State The state of the host controller that will be set.\r
219\r
220 @return EFI_SUCCESS : The USB host controller was successfully placed\r
221 @return in the state specified by State.\r
222 @return EFI_INVALID_PARAMETER : State is invalid.\r
223 @return EFI_DEVICE_ERROR : Failed to set the state due to device error.\r
224\r
225**/\r
226STATIC\r
227EFI_STATUS\r
228EFIAPI\r
229EhcSetState (\r
230 IN EFI_USB2_HC_PROTOCOL *This,\r
231 IN EFI_USB_HC_STATE State\r
232 )\r
233{\r
234 USB2_HC_DEV *Ehc;\r
235 EFI_TPL OldTpl;\r
236 EFI_STATUS Status;\r
237 EFI_USB_HC_STATE CurState;\r
238\r
239 Status = EhcGetState (This, &CurState);\r
240\r
241 if (EFI_ERROR (Status)) {\r
242 return EFI_DEVICE_ERROR;\r
243 }\r
244\r
245 if (CurState == State) {\r
246 return EFI_SUCCESS;\r
247 }\r
248\r
249 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
250 Ehc = EHC_FROM_THIS (This);\r
251\r
252 switch (State) {\r
253 case EfiUsbHcStateHalt:\r
254 Status = EhcHaltHC (Ehc, EHC_GENERIC_TIME);\r
255 break;\r
256\r
257 case EfiUsbHcStateOperational:\r
258 if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR)) {\r
259 Status = EFI_DEVICE_ERROR;\r
260 break;\r
261 }\r
262\r
263 Status = EhcRunHC (Ehc, EHC_GENERIC_TIME);\r
264 break;\r
265\r
266 case EfiUsbHcStateSuspend:\r
267 Status = EFI_UNSUPPORTED;\r
268 break;\r
269\r
270 default:\r
271 Status = EFI_INVALID_PARAMETER;\r
272 }\r
273\r
274 EHC_DEBUG (("EhcSetState: exit status %r\n", Status));\r
275 gBS->RestoreTPL (OldTpl);\r
276 return Status;\r
277}\r
278\r
279\r
280/**\r
281 Retrieves the current status of a USB root hub port.\r
282\r
283 @param This This EFI_USB2_HC_PROTOCOL instance.\r
284 @param PortNumber The root hub port to retrieve the state from. This\r
285 value is zero-based.\r
286 @param PortStatus Variable to receive the port state\r
287\r
288 @return EFI_SUCCESS : The status of the USB root hub port specified\r
289 @return by PortNumber was returned in PortStatus.\r
290 @return EFI_INVALID_PARAMETER : PortNumber is invalid.\r
291 @return EFI_DEVICE_ERROR : Can't read register\r
292\r
293**/\r
294STATIC\r
295EFI_STATUS\r
296EFIAPI\r
297EhcGetRootHubPortStatus (\r
298 IN CONST EFI_USB2_HC_PROTOCOL *This,\r
299 IN CONST UINT8 PortNumber,\r
300 OUT EFI_USB_PORT_STATUS *PortStatus\r
301 )\r
302{\r
303 USB2_HC_DEV *Ehc;\r
304 EFI_TPL OldTpl;\r
305 UINT32 Offset;\r
306 UINT32 State;\r
307 UINT32 TotalPort;\r
308 UINTN Index;\r
309 UINTN MapSize;\r
310 EFI_STATUS Status;\r
311\r
312 if (PortStatus == NULL) {\r
313 return EFI_INVALID_PARAMETER;\r
314 }\r
315\r
316 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
317\r
318 Ehc = EHC_FROM_THIS (This);\r
319 Status = EFI_SUCCESS;\r
320\r
321 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);\r
322\r
323 if (PortNumber >= TotalPort) {\r
324 Status = EFI_INVALID_PARAMETER;\r
325 goto ON_EXIT;\r
326 }\r
327\r
328 Offset = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));\r
329 PortStatus->PortStatus = 0;\r
330 PortStatus->PortChangeStatus = 0;\r
331\r
332 State = EhcReadOpReg (Ehc, Offset);\r
333\r
334 //\r
335 // Identify device speed. If in K state, it is low speed.\r
336 // If the port is enabled after reset, the device is of\r
337 // high speed. The USB bus driver should retrieve the actual\r
338 // port speed after reset.\r
339 //\r
340 if (EHC_BIT_IS_SET (State, PORTSC_LINESTATE_K)) {\r
341 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
342\r
343 } else if (EHC_BIT_IS_SET (State, PORTSC_ENABLED)) {\r
344 PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;\r
345 }\r
346\r
347 //\r
348 // Convert the EHCI port/port change state to UEFI status\r
349 //\r
350 MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);\r
351\r
352 for (Index = 0; Index < MapSize; Index++) {\r
353 if (EHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {\r
c52fa98c 354 PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);\r
913cb9dc 355 }\r
356 }\r
357\r
358 MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);\r
359\r
360 for (Index = 0; Index < MapSize; Index++) {\r
361 if (EHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {\r
c52fa98c 362 PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);\r
913cb9dc 363 }\r
364 }\r
365\r
366ON_EXIT:\r
367 gBS->RestoreTPL (OldTpl);\r
368 return Status;\r
369}\r
370\r
371\r
372/**\r
373 Sets a feature for the specified root hub port.\r
374\r
375 @param This This EFI_USB2_HC_PROTOCOL instance.\r
376 @param PortNumber Root hub port to set.\r
377 @param PortFeature Feature to set\r
378\r
379 @return EFI_SUCCESS : The feature specified by PortFeature was set\r
380 @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
381 @return EFI_DEVICE_ERROR : Can't read register\r
382\r
383**/\r
384STATIC\r
385EFI_STATUS\r
386EFIAPI\r
387EhcSetRootHubPortFeature (\r
388 IN EFI_USB2_HC_PROTOCOL *This,\r
389 IN UINT8 PortNumber,\r
390 IN EFI_USB_PORT_FEATURE PortFeature\r
391 )\r
392{\r
393 USB2_HC_DEV *Ehc;\r
394 EFI_TPL OldTpl;\r
395 UINT32 Offset;\r
396 UINT32 State;\r
397 UINT32 TotalPort;\r
398 EFI_STATUS Status;\r
399\r
400 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
401 Ehc = EHC_FROM_THIS (This);\r
402 Status = EFI_SUCCESS;\r
403\r
404 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);\r
405\r
406 if (PortNumber >= TotalPort) {\r
407 Status = EFI_INVALID_PARAMETER;\r
408 goto ON_EXIT;\r
409 }\r
410\r
411 Offset = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));\r
412 State = EhcReadOpReg (Ehc, Offset);\r
413\r
414 //\r
415 // Mask off the port status change bits, these bits are\r
416 // write clean bit\r
417 //\r
418 State &= ~PORTSC_CHANGE_MASK;\r
419\r
420 switch (PortFeature) {\r
421 case EfiUsbPortEnable:\r
422 //\r
423 // Sofeware can't set this bit, Port can only be enable by\r
424 // EHCI as a part of the reset and enable\r
425 //\r
426 State |= PORTSC_ENABLED;\r
427 EhcWriteOpReg (Ehc, Offset, State);\r
428 break;\r
429\r
430 case EfiUsbPortSuspend:\r
431 State |= PORTSC_SUSPEND;\r
432 EhcWriteOpReg (Ehc, Offset, State);\r
433 break;\r
434\r
435 case EfiUsbPortReset:\r
436 //\r
437 // Make sure Host Controller not halt before reset it\r
438 //\r
439 if (EhcIsHalt (Ehc)) {\r
440 Status = EhcRunHC (Ehc, EHC_GENERIC_TIME);\r
441\r
442 if (EFI_ERROR (Status)) {\r
443 EHC_DEBUG (("EhcSetRootHubPortFeature :failed to start HC - %r\n", Status));\r
444 break;\r
445 }\r
446 }\r
447\r
448 //\r
449 // Set one to PortReset bit must also set zero to PortEnable bit\r
450 //\r
451 State |= PORTSC_RESET;\r
452 State &= ~PORTSC_ENABLED;\r
453 EhcWriteOpReg (Ehc, Offset, State);\r
454 break;\r
455\r
456 case EfiUsbPortPower:\r
457 //\r
458 // Not supported, ignore the operation\r
459 //\r
460 Status = EFI_SUCCESS;\r
461 break;\r
462\r
463 case EfiUsbPortOwner:\r
464 State |= PORTSC_OWNER;\r
465 EhcWriteOpReg (Ehc, Offset, State);\r
466 break;\r
467\r
468 default:\r
469 Status = EFI_INVALID_PARAMETER;\r
470 }\r
471\r
472ON_EXIT:\r
473 EHC_DEBUG (("EhcSetRootHubPortFeature: exit status %r\n", Status));\r
474\r
475 gBS->RestoreTPL (OldTpl);\r
476 return Status;\r
477}\r
478\r
479\r
480/**\r
481 Clears a feature for the specified root hub port.\r
482\r
483 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
484 @param PortNumber Specifies the root hub port whose feature is\r
485 requested to be cleared.\r
486 @param PortFeature Indicates the feature selector associated with the\r
487 feature clear request.\r
488\r
489 @return EFI_SUCCESS : The feature specified by PortFeature was cleared\r
490 @return for the USB root hub port specified by PortNumber.\r
491 @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
492 @return EFI_DEVICE_ERROR : Can't read register\r
493\r
494**/\r
495STATIC\r
496EFI_STATUS\r
497EFIAPI\r
498EhcClearRootHubPortFeature (\r
499 IN EFI_USB2_HC_PROTOCOL *This,\r
500 IN UINT8 PortNumber,\r
501 IN EFI_USB_PORT_FEATURE PortFeature\r
502 )\r
503{\r
504 USB2_HC_DEV *Ehc;\r
505 EFI_TPL OldTpl;\r
506 UINT32 Offset;\r
507 UINT32 State;\r
508 UINT32 TotalPort;\r
509 EFI_STATUS Status;\r
510\r
511 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
512 Ehc = EHC_FROM_THIS (This);\r
513 Status = EFI_SUCCESS;\r
514\r
515 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);\r
516\r
517 if (PortNumber >= TotalPort) {\r
518 Status = EFI_INVALID_PARAMETER;\r
519 goto ON_EXIT;\r
520 }\r
521\r
522 Offset = EHC_PORT_STAT_OFFSET + (4 * PortNumber);\r
523 State = EhcReadOpReg (Ehc, Offset);\r
524 State &= ~PORTSC_CHANGE_MASK;\r
525\r
526 switch (PortFeature) {\r
527 case EfiUsbPortEnable:\r
528 //\r
529 // Clear PORT_ENABLE feature means disable port.\r
530 //\r
531 State &= ~PORTSC_ENABLED;\r
532 EhcWriteOpReg (Ehc, Offset, State);\r
533 break;\r
534\r
535 case EfiUsbPortSuspend:\r
536 //\r
537 // A write of zero to this bit is ignored by the host\r
538 // controller. The host controller will unconditionally\r
539 // set this bit to a zero when:\r
540 // 1. software sets the Forct Port Resume bit to a zero from a one.\r
541 // 2. software sets the Port Reset bit to a one frome a zero.\r
542 //\r
543 State &= ~PORSTSC_RESUME;\r
544 EhcWriteOpReg (Ehc, Offset, State);\r
545 break;\r
546\r
547 case EfiUsbPortReset:\r
548 //\r
549 // Clear PORT_RESET means clear the reset signal.\r
550 //\r
551 State &= ~PORTSC_RESET;\r
552 EhcWriteOpReg (Ehc, Offset, State);\r
553 break;\r
554\r
555 case EfiUsbPortOwner:\r
556 //\r
557 // Clear port owner means this port owned by EHC\r
558 //\r
559 State &= ~PORTSC_OWNER;\r
560 EhcWriteOpReg (Ehc, Offset, State);\r
561 break;\r
562\r
563 case EfiUsbPortConnectChange:\r
564 //\r
565 // Clear connect status change\r
566 //\r
567 State |= PORTSC_CONN_CHANGE;\r
568 EhcWriteOpReg (Ehc, Offset, State);\r
569 break;\r
570\r
571 case EfiUsbPortEnableChange:\r
572 //\r
573 // Clear enable status change\r
574 //\r
575 State |= PORTSC_ENABLE_CHANGE;\r
576 EhcWriteOpReg (Ehc, Offset, State);\r
577 break;\r
578\r
579 case EfiUsbPortOverCurrentChange:\r
580 //\r
581 // Clear PortOverCurrent change\r
582 //\r
583 State |= PORTSC_OVERCUR_CHANGE;\r
584 EhcWriteOpReg (Ehc, Offset, State);\r
585 break;\r
586\r
587 case EfiUsbPortPower:\r
588 case EfiUsbPortSuspendChange:\r
589 case EfiUsbPortResetChange:\r
590 //\r
591 // Not supported or not related operation\r
592 //\r
593 break;\r
594\r
595 default:\r
596 Status = EFI_INVALID_PARAMETER;\r
597 break;\r
598 }\r
599\r
600ON_EXIT:\r
601 EHC_DEBUG (("EhcClearRootHubPortFeature: exit status %r\n", Status));\r
602 gBS->RestoreTPL (OldTpl);\r
603 return Status;\r
604}\r
605\r
606\r
607/**\r
608 Submits control transfer to a target USB device.\r
609\r
610 @param This This EFI_USB2_HC_PROTOCOL instance.\r
611 @param DeviceAddress The target device address\r
612 @param DeviceSpeed Target device speed.\r
613 @param MaximumPacketLength Maximum packet size the default control transfer\r
614 endpoint is capable of sending or receiving.\r
615 @param Request USB device request to send\r
616 @param TransferDirection Specifies the data direction for the data stage\r
617 @param Data Data buffer to be transmitted or received from USB\r
618 device.\r
619 @param DataLength The size (in bytes) of the data buffer\r
620 @param TimeOut Indicates the maximum timeout, in millisecond,\r
621 @param Translator Transaction translator to be used by this device.\r
622 @param TransferResult Return the result of this control transfer.\r
623\r
624 @return EFI_SUCCESS : Transfer was completed successfully.\r
625 @return EFI_OUT_OF_RESOURCES : The transfer failed due to lack of resources.\r
626 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
627 @return EFI_TIMEOUT : Transfer failed due to timeout.\r
628 @return EFI_DEVICE_ERROR : Transfer failed due to host controller or device error.\r
629\r
630**/\r
631STATIC\r
632EFI_STATUS\r
633EFIAPI\r
634EhcControlTransfer (\r
635 IN EFI_USB2_HC_PROTOCOL *This,\r
636 IN UINT8 DeviceAddress,\r
637 IN UINT8 DeviceSpeed,\r
638 IN UINTN MaximumPacketLength,\r
639 IN EFI_USB_DEVICE_REQUEST *Request,\r
640 IN EFI_USB_DATA_DIRECTION TransferDirection,\r
641 IN OUT VOID *Data,\r
642 IN OUT UINTN *DataLength,\r
643 IN UINTN TimeOut,\r
644 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
645 OUT UINT32 *TransferResult\r
646 )\r
647{\r
648 USB2_HC_DEV *Ehc;\r
649 URB *Urb;\r
650 EFI_TPL OldTpl;\r
651 UINT8 Endpoint;\r
652 EFI_STATUS Status;\r
653\r
654 //\r
655 // Validate parameters\r
656 //\r
657 if ((Request == NULL) || (TransferResult == NULL)) {\r
658 return EFI_INVALID_PARAMETER;\r
659 }\r
660\r
661 if ((TransferDirection != EfiUsbDataIn) &&\r
662 (TransferDirection != EfiUsbDataOut) &&\r
663 (TransferDirection != EfiUsbNoData)) {\r
664 return EFI_INVALID_PARAMETER;\r
665 }\r
666\r
667 if ((TransferDirection == EfiUsbNoData) &&\r
668 ((Data != NULL) || (*DataLength != 0))) {\r
669 return EFI_INVALID_PARAMETER;\r
670 }\r
671\r
672 if ((TransferDirection != EfiUsbNoData) &&\r
673 ((Data == NULL) || (*DataLength == 0))) {\r
674 return EFI_INVALID_PARAMETER;\r
675 }\r
676\r
677 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&\r
678 (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {\r
679 return EFI_INVALID_PARAMETER;\r
680 }\r
681\r
682 if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {\r
683 return EFI_INVALID_PARAMETER;\r
684 }\r
685\r
686 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
687 Ehc = EHC_FROM_THIS (This);\r
688\r
689 Status = EFI_DEVICE_ERROR;\r
690 *TransferResult = EFI_USB_ERR_SYSTEM;\r
691\r
692 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {\r
693 EHC_ERROR (("EhcControlTransfer: HC halted at entrance\n"));\r
694\r
695 EhcAckAllInterrupt (Ehc);\r
696 goto ON_EXIT;\r
697 }\r
698\r
699 EhcAckAllInterrupt (Ehc);\r
700\r
701 //\r
702 // Create a new URB, insert it into the asynchronous\r
703 // schedule list, then poll the execution status.\r
704 //\r
705 //\r
706 // Encode the direction in address, although default control\r
707 // endpoint is bidirectional. EhcCreateUrb expects this\r
708 // combination of Ep addr and its direction.\r
709 //\r
c52fa98c 710 Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));\r
913cb9dc 711 Urb = EhcCreateUrb (\r
712 Ehc,\r
713 DeviceAddress,\r
714 Endpoint,\r
715 DeviceSpeed,\r
716 0,\r
717 MaximumPacketLength,\r
718 Translator,\r
719 EHC_CTRL_TRANSFER,\r
720 Request,\r
721 Data,\r
722 *DataLength,\r
723 NULL,\r
724 NULL,\r
725 1\r
726 );\r
727\r
728 if (Urb == NULL) {\r
729 EHC_ERROR (("EhcControlTransfer: failed to create URB"));\r
730\r
731 Status = EFI_OUT_OF_RESOURCES;\r
732 goto ON_EXIT;\r
733 }\r
734\r
735 EhcLinkQhToAsync (Ehc, Urb->Qh);\r
736 Status = EhcExecTransfer (Ehc, Urb, TimeOut);\r
737 EhcUnlinkQhFromAsync (Ehc, Urb->Qh);\r
738\r
739 //\r
740 // Get the status from URB. The result is updated in EhcCheckUrbResult\r
741 // which is called by EhcExecTransfer\r
742 //\r
743 *TransferResult = Urb->Result;\r
744 *DataLength = Urb->Completed;\r
745\r
746 if (*TransferResult == EFI_USB_NOERROR) {\r
747 Status = EFI_SUCCESS;\r
748 }\r
749\r
750 EhcAckAllInterrupt (Ehc);\r
751 EhcFreeUrb (Ehc, Urb);\r
752\r
753ON_EXIT:\r
754 Ehc->PciIo->Flush (Ehc->PciIo);\r
755 gBS->RestoreTPL (OldTpl);\r
756\r
757 if (EFI_ERROR (Status)) {\r
758 EHC_ERROR (("EhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
759 }\r
760\r
761 return Status;\r
762}\r
763\r
764\r
765/**\r
766 Submits bulk transfer to a bulk endpoint of a USB device.\r
767\r
768 @param This This EFI_USB2_HC_PROTOCOL instance.\r
769 @param DeviceAddress Target device address\r
770 @param EndPointAddress Endpoint number and its direction in bit 7. .\r
771 @param DeviceSpeed Device speed, Low speed device doesn't support bulk\r
772 transfer.\r
773 @param MaximumPacketLength Maximum packet size the endpoint is capable of\r
774 sending or receiving.\r
775 @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
776 @param Data Array of pointers to the buffers of data to transmit\r
777 from or receive into.\r
778 @param DataLength The lenght of the data buffer\r
779 @param DataToggle On input, the initial data toggle for the transfer;\r
780 On output, it is updated to to next data toggle to\r
781 use of the subsequent bulk\r
782 transfer.\r
783 @param Translator A pointr to the transaction translator data.\r
784 @param TimeOut Indicates the maximum time, in millisecond, which\r
785 the transfer is allowed to complete.\r
786 @param TransferResult A pointer to the detailed result information of the\r
787 bulk transfer.\r
788\r
789 @return EFI_SUCCESS : The transfer was completed successfully.\r
790 @return EFI_OUT_OF_RESOURCES : The transfer failed due to lack of resource.\r
791 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
792 @return EFI_TIMEOUT : The transfer failed due to timeout.\r
793 @return EFI_DEVICE_ERROR : The transfer failed due to host controller error.\r
794\r
795**/\r
796STATIC\r
797EFI_STATUS\r
798EFIAPI\r
799EhcBulkTransfer (\r
800 IN EFI_USB2_HC_PROTOCOL *This,\r
801 IN UINT8 DeviceAddress,\r
802 IN UINT8 EndPointAddress,\r
803 IN UINT8 DeviceSpeed,\r
804 IN UINTN MaximumPacketLength,\r
805 IN UINT8 DataBuffersNumber,\r
806 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
807 IN OUT UINTN *DataLength,\r
808 IN OUT UINT8 *DataToggle,\r
809 IN UINTN TimeOut,\r
810 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
811 OUT UINT32 *TransferResult\r
812 )\r
813{\r
814 USB2_HC_DEV *Ehc;\r
815 URB *Urb;\r
816 EFI_TPL OldTpl;\r
817 EFI_STATUS Status;\r
818\r
819 //\r
820 // Validate the parameters\r
821 //\r
822 if ((DataLength == NULL) || (*DataLength == 0) ||\r
823 (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {\r
824 return EFI_INVALID_PARAMETER;\r
825 }\r
826\r
827 if ((*DataToggle != 0) && (*DataToggle != 1)) {\r
828 return EFI_INVALID_PARAMETER;\r
829 }\r
830\r
831 if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||\r
832 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||\r
833 ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) {\r
834 return EFI_INVALID_PARAMETER;\r
835 }\r
836\r
837 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
838 Ehc = EHC_FROM_THIS (This);\r
839\r
840 *TransferResult = EFI_USB_ERR_SYSTEM;\r
841 Status = EFI_DEVICE_ERROR;\r
842\r
843 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {\r
844 EHC_ERROR (("EhcBulkTransfer: HC is halted\n"));\r
845\r
846 EhcAckAllInterrupt (Ehc);\r
847 goto ON_EXIT;\r
848 }\r
849\r
850 EhcAckAllInterrupt (Ehc);\r
851\r
852 //\r
853 // Create a new URB, insert it into the asynchronous\r
854 // schedule list, then poll the execution status.\r
855 //\r
856 Urb = EhcCreateUrb (\r
857 Ehc,\r
858 DeviceAddress,\r
859 EndPointAddress,\r
860 DeviceSpeed,\r
861 *DataToggle,\r
862 MaximumPacketLength,\r
863 Translator,\r
864 EHC_BULK_TRANSFER,\r
865 NULL,\r
866 Data[0],\r
867 *DataLength,\r
868 NULL,\r
869 NULL,\r
870 1\r
871 );\r
872\r
873 if (Urb == NULL) {\r
874 EHC_ERROR (("EhcBulkTransfer: failed to create URB\n"));\r
875\r
876 Status = EFI_OUT_OF_RESOURCES;\r
877 goto ON_EXIT;\r
878 }\r
879\r
880 EhcLinkQhToAsync (Ehc, Urb->Qh);\r
881 Status = EhcExecTransfer (Ehc, Urb, TimeOut);\r
882 EhcUnlinkQhFromAsync (Ehc, Urb->Qh);\r
883\r
884 *TransferResult = Urb->Result;\r
885 *DataLength = Urb->Completed;\r
886 *DataToggle = Urb->DataToggle;\r
887\r
888 if (*TransferResult == EFI_USB_NOERROR) {\r
889 Status = EFI_SUCCESS;\r
890 }\r
891\r
892 EhcAckAllInterrupt (Ehc);\r
893 EhcFreeUrb (Ehc, Urb);\r
894\r
895ON_EXIT:\r
896 Ehc->PciIo->Flush (Ehc->PciIo);\r
897 gBS->RestoreTPL (OldTpl);\r
898\r
899 if (EFI_ERROR (Status)) {\r
900 EHC_ERROR (("EhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
901 }\r
902\r
903 return Status;\r
904}\r
905\r
906\r
907/**\r
908 Submits an asynchronous interrupt transfer to an\r
909 interrupt endpoint of a USB device.\r
910\r
911 @param This This EFI_USB2_HC_PROTOCOL instance.\r
912 @param DeviceAddress Target device address\r
913 @param EndPointAddress Endpoint number and its direction encoded in bit 7\r
914 @param DeviceSpeed Indicates device speed.\r
915 @param MaximumPacketLength Maximum packet size the target endpoint is capable\r
916 @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt\r
917 transfer If FALSE, to remove the specified\r
918 asynchronous interrupt\r
919 @param DataToggle On input, the initial data toggle to use; on output,\r
920 it is updated to indicate the next data toggle\r
921 @param PollingInterval The he interval, in milliseconds, that the transfer\r
922 is polled.\r
923 @param DataLength The length of data to receive at the rate specified\r
924 by PollingInterval.\r
925 @param Translator Transaction translator to use.\r
926 @param CallBackFunction Function to call at the rate specified by\r
927 PollingInterval\r
928 @param Context Context to CallBackFunction.\r
929\r
930 @return EFI_SUCCESS : The request has been successfully submitted or canceled.\r
931 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
932 @return EFI_OUT_OF_RESOURCES : The request failed due to a lack of resources.\r
933 @return EFI_DEVICE_ERROR : The transfer failed due to host controller error.\r
934\r
935**/\r
936STATIC\r
937EFI_STATUS\r
938EFIAPI\r
939EhcAsyncInterruptTransfer (\r
940 IN EFI_USB2_HC_PROTOCOL * This,\r
941 IN UINT8 DeviceAddress,\r
942 IN UINT8 EndPointAddress,\r
943 IN UINT8 DeviceSpeed,\r
944 IN UINTN MaximumPacketLength,\r
945 IN BOOLEAN IsNewTransfer,\r
946 IN OUT UINT8 *DataToggle,\r
947 IN UINTN PollingInterval,\r
948 IN UINTN DataLength,\r
949 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,\r
950 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,\r
951 IN VOID *Context OPTIONAL\r
952 )\r
953{\r
954 USB2_HC_DEV *Ehc;\r
955 URB *Urb;\r
956 EFI_TPL OldTpl;\r
957 EFI_STATUS Status;\r
958 UINT8 *Data;\r
959\r
960 //\r
961 // Validate parameters\r
962 //\r
963 if (!EHCI_IS_DATAIN (EndPointAddress)) {\r
964 return EFI_INVALID_PARAMETER;\r
965 }\r
966\r
967 if (IsNewTransfer) {\r
968 if (DataLength == 0) {\r
969 return EFI_INVALID_PARAMETER;\r
970 }\r
971\r
972 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
973 return EFI_INVALID_PARAMETER;\r
974 }\r
975\r
976 if ((PollingInterval > 255) || (PollingInterval < 1)) {\r
977 return EFI_INVALID_PARAMETER;\r
978 }\r
979 }\r
980\r
981 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
982 Ehc = EHC_FROM_THIS (This);\r
983\r
984 //\r
985 // Delete Async interrupt transfer request. DataToggle will return\r
986 // the next data toggle to use.\r
987 //\r
988 if (!IsNewTransfer) {\r
989 Status = EhciDelAsyncIntTransfer (Ehc, DeviceAddress, EndPointAddress, DataToggle);\r
990\r
991 EHC_DEBUG (("EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status));\r
992 goto ON_EXIT;\r
993 }\r
994\r
995 Status = EFI_SUCCESS;\r
996\r
997 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {\r
998 EHC_ERROR (("EhcAsyncInterruptTransfer: HC is halt\n"));\r
999 EhcAckAllInterrupt (Ehc);\r
1000\r
1001 Status = EFI_DEVICE_ERROR;\r
1002 goto ON_EXIT;\r
1003 }\r
1004\r
1005 EhcAckAllInterrupt (Ehc);\r
1006\r
1007 Data = AllocatePool (DataLength);\r
1008\r
1009 if (Data == NULL) {\r
1010 EHC_ERROR (("EhcAsyncInterruptTransfer: failed to allocate buffer\n"));\r
1011\r
1012 Status = EFI_OUT_OF_RESOURCES;\r
1013 goto ON_EXIT;\r
1014 }\r
1015\r
1016 Urb = EhcCreateUrb (\r
1017 Ehc,\r
1018 DeviceAddress,\r
1019 EndPointAddress,\r
1020 DeviceSpeed,\r
1021 *DataToggle,\r
1022 MaximumPacketLength,\r
1023 Translator,\r
1024 EHC_INT_TRANSFER_ASYNC,\r
1025 NULL,\r
1026 Data,\r
1027 DataLength,\r
1028 CallBackFunction,\r
1029 Context,\r
1030 PollingInterval\r
1031 );\r
1032\r
1033 if (Urb == NULL) {\r
1034 EHC_ERROR (("EhcAsyncInterruptTransfer: failed to create URB\n"));\r
1035\r
1036 gBS->FreePool (Data);\r
1037 Status = EFI_OUT_OF_RESOURCES;\r
1038 goto ON_EXIT;\r
1039 }\r
1040\r
1041 //\r
1042 // New asynchronous transfer must inserted to the head.\r
1043 // Check the comments in EhcMoniteAsyncRequests\r
1044 //\r
1045 EhcLinkQhToPeriod (Ehc, Urb->Qh);\r
1046 InsertHeadList (&Ehc->AsyncIntTransfers, &Urb->UrbList);\r
1047\r
1048ON_EXIT:\r
1049 Ehc->PciIo->Flush (Ehc->PciIo);\r
1050 gBS->RestoreTPL (OldTpl);\r
1051\r
1052 return Status;\r
1053}\r
1054\r
1055\r
1056/**\r
1057 Submits synchronous interrupt transfer to an interrupt endpoint\r
1058 of a USB device.\r
1059\r
1060 @param This This EFI_USB2_HC_PROTOCOL instance.\r
1061 @param DeviceAddress Target device address\r
1062 @param EndPointAddress Endpoint number and its direction encoded in bit 7\r
1063 @param DeviceSpeed Indicates device speed.\r
1064 @param MaximumPacketLength Maximum packet size the target endpoint is capable\r
1065 of sending or receiving.\r
1066 @param Data Buffer of data that will be transmitted to USB\r
1067 device or received from USB device.\r
1068 @param DataLength On input, the size, in bytes, of the data buffer; On\r
1069 output, the number of bytes transferred.\r
1070 @param DataToggle On input, the initial data toggle to use; on output,\r
1071 it is updated to indicate the next data toggle\r
1072 @param TimeOut Maximum time, in second, to complete\r
1073 @param Translator Transaction translator to use.\r
1074 @param TransferResult Variable to receive the transfer result\r
1075\r
1076 @return EFI_SUCCESS : The transfer was completed successfully.\r
1077 @return EFI_OUT_OF_RESOURCES : The transfer failed due to lack of resource.\r
1078 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1079 @return EFI_TIMEOUT : The transfer failed due to timeout.\r
1080 @return EFI_DEVICE_ERROR : The failed due to host controller or device error\r
1081\r
1082**/\r
1083STATIC\r
1084EFI_STATUS\r
1085EFIAPI\r
1086EhcSyncInterruptTransfer (\r
1087 IN EFI_USB2_HC_PROTOCOL *This,\r
1088 IN UINT8 DeviceAddress,\r
1089 IN UINT8 EndPointAddress,\r
1090 IN UINT8 DeviceSpeed,\r
1091 IN UINTN MaximumPacketLength,\r
1092 IN OUT VOID *Data,\r
1093 IN OUT UINTN *DataLength,\r
1094 IN OUT UINT8 *DataToggle,\r
1095 IN UINTN TimeOut,\r
1096 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1097 OUT UINT32 *TransferResult\r
1098 )\r
1099{\r
1100 USB2_HC_DEV *Ehc;\r
1101 EFI_TPL OldTpl;\r
1102 URB *Urb;\r
1103 EFI_STATUS Status;\r
1104\r
1105 //\r
1106 // Validates parameters\r
1107 //\r
1108 if ((DataLength == NULL) || (*DataLength == 0) ||\r
1109 (Data == NULL) || (TransferResult == NULL)) {\r
1110 return EFI_INVALID_PARAMETER;\r
1111 }\r
1112\r
1113 if (!EHCI_IS_DATAIN (EndPointAddress)) {\r
1114 return EFI_INVALID_PARAMETER;\r
1115 }\r
1116\r
1117 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
1118 return EFI_INVALID_PARAMETER;\r
1119 }\r
1120\r
1121 if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) ||\r
1122 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||\r
1123 ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) {\r
1124 return EFI_INVALID_PARAMETER;\r
1125 }\r
1126\r
1127 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
1128 Ehc = EHC_FROM_THIS (This);\r
1129\r
1130 *TransferResult = EFI_USB_ERR_SYSTEM;\r
1131 Status = EFI_DEVICE_ERROR;\r
1132\r
1133 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {\r
1134 EHC_ERROR (("EhcSyncInterruptTransfer: HC is halt\n"));\r
1135\r
1136 EhcAckAllInterrupt (Ehc);\r
1137 goto ON_EXIT;\r
1138 }\r
1139\r
1140 EhcAckAllInterrupt (Ehc);\r
1141\r
1142 Urb = EhcCreateUrb (\r
1143 Ehc,\r
1144 DeviceAddress,\r
1145 EndPointAddress,\r
1146 DeviceSpeed,\r
1147 *DataToggle,\r
1148 MaximumPacketLength,\r
1149 Translator,\r
1150 EHC_INT_TRANSFER_SYNC,\r
1151 NULL,\r
1152 Data,\r
1153 *DataLength,\r
1154 NULL,\r
1155 NULL,\r
1156 1\r
1157 );\r
1158\r
1159 if (Urb == NULL) {\r
1160 EHC_ERROR (("EhcSyncInterruptTransfer: failed to create URB\n"));\r
1161\r
1162 Status = EFI_OUT_OF_RESOURCES;\r
1163 goto ON_EXIT;\r
1164 }\r
1165\r
1166 EhcLinkQhToPeriod (Ehc, Urb->Qh);\r
1167 Status = EhcExecTransfer (Ehc, Urb, TimeOut);\r
1168 EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);\r
1169\r
1170 *TransferResult = Urb->Result;\r
1171 *DataLength = Urb->Completed;\r
1172 *DataToggle = Urb->DataToggle;\r
1173\r
1174 if (*TransferResult == EFI_USB_NOERROR) {\r
1175 Status = EFI_SUCCESS;\r
1176 }\r
1177\r
1178ON_EXIT:\r
1179 Ehc->PciIo->Flush (Ehc->PciIo);\r
1180 gBS->RestoreTPL (OldTpl);\r
1181\r
1182 if (EFI_ERROR (Status)) {\r
1183 EHC_ERROR (("EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
1184 }\r
1185\r
1186 return Status;\r
1187}\r
1188\r
1189\r
1190/**\r
1191 Submits isochronous transfer to a target USB device.\r
1192\r
1193 @param This This EFI_USB2_HC_PROTOCOL instance.\r
1194 @param DeviceAddress Target device address\r
1195 @param EndPointAddress End point address with its direction\r
1196 @param DeviceSpeed Device speed, Low speed device doesn't support this\r
1197 type.\r
1198 @param MaximumPacketLength Maximum packet size that the endpoint is capable of\r
1199 sending or receiving.\r
1200 @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
1201 @param Data Array of pointers to the buffers of data that will\r
1202 be transmitted to USB device or received from USB\r
1203 device.\r
1204 @param DataLength The size, in bytes, of the data buffer\r
1205 @param Translator Transaction translator to use.\r
1206 @param TransferResult Variable to receive the transfer result\r
1207\r
1208 @return EFI_UNSUPPORTED : Isochronous transfer is unsupported.\r
1209\r
1210**/\r
1211STATIC\r
1212EFI_STATUS\r
1213EFIAPI\r
1214EhcIsochronousTransfer (\r
1215 IN EFI_USB2_HC_PROTOCOL *This,\r
1216 IN UINT8 DeviceAddress,\r
1217 IN UINT8 EndPointAddress,\r
1218 IN UINT8 DeviceSpeed,\r
1219 IN UINTN MaximumPacketLength,\r
1220 IN UINT8 DataBuffersNumber,\r
1221 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1222 IN UINTN DataLength,\r
1223 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1224 OUT UINT32 *TransferResult\r
1225 )\r
1226{\r
1227 return EFI_UNSUPPORTED;\r
1228}\r
1229\r
1230\r
1231/**\r
1232 Submits Async isochronous transfer to a target USB device.\r
1233\r
1234 @param This This EFI_USB2_HC_PROTOCOL instance.\r
1235 @param DeviceAddress Target device address\r
1236 @param EndPointAddress End point address with its direction\r
1237 @param DeviceSpeed Device speed, Low speed device doesn't support this\r
1238 type.\r
1239 @param MaximumPacketLength Maximum packet size that the endpoint is capable of\r
1240 sending or receiving.\r
1241 @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
1242 @param Data Array of pointers to the buffers of data that will\r
1243 be transmitted to USB device or received from USB\r
1244 device.\r
1245 @param DataLength The size, in bytes, of the data buffer\r
1246 @param Translator Transaction translator to use.\r
1247 @param IsochronousCallBack Function to be called when the transfer complete\r
1248 @param Context Context passed to the call back function as\r
1249 parameter\r
1250\r
1251 @return EFI_UNSUPPORTED : Isochronous transfer isn't supported\r
1252\r
1253**/\r
1254STATIC\r
1255EFI_STATUS\r
1256EFIAPI\r
1257EhcAsyncIsochronousTransfer (\r
1258 IN EFI_USB2_HC_PROTOCOL *This,\r
1259 IN UINT8 DeviceAddress,\r
1260 IN UINT8 EndPointAddress,\r
1261 IN UINT8 DeviceSpeed,\r
1262 IN UINTN MaximumPacketLength,\r
1263 IN UINT8 DataBuffersNumber,\r
1264 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1265 IN UINTN DataLength,\r
1266 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1267 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
1268 IN VOID *Context\r
1269 )\r
1270{\r
1271 return EFI_UNSUPPORTED;\r
1272}\r
1273\r
913cb9dc 1274EFI_STATUS\r
1275EFIAPI\r
1276EhcDriverEntryPoint (\r
1277 IN EFI_HANDLE ImageHandle,\r
1278 IN EFI_SYSTEM_TABLE *SystemTable\r
1279 )\r
1280/*++\r
1281\r
1282Routine Description:\r
1283\r
1284 Entry point for EFI drivers.\r
1285\r
1286Arguments:\r
1287\r
1288 ImageHandle - EFI_HANDLE\r
1289 SystemTable - EFI_SYSTEM_TABLE\r
1290\r
1291Returns:\r
1292\r
1293 EFI_SUCCESS Success\r
1294 EFI_DEVICE_ERROR Fail\r
1295\r
1296--*/\r
1297{\r
f527bce3 1298 return EfiLibInstallDriverBindingComponentName2 (\r
913cb9dc 1299 ImageHandle,\r
1300 SystemTable,\r
1301 &gEhciDriverBinding,\r
1302 ImageHandle,\r
1303 &gEhciComponentName,\r
f527bce3 1304 &gEhciComponentName2\r
913cb9dc 1305 );\r
1306}\r
1307\r
1308\r
1309/**\r
1310 Test to see if this driver supports ControllerHandle. Any\r
1311 ControllerHandle that has Usb2HcProtocol installed will\r
1312 be supported.\r
1313\r
1314 @param This Protocol instance pointer.\r
1315 @param Controlle Handle of device to test\r
1316 @param RemainingDevicePath Not used\r
1317\r
1318 @return EFI_SUCCESS : This driver supports this device.\r
1319 @return EFI_UNSUPPORTED : This driver does not support this device.\r
1320\r
1321**/\r
1322EFI_STATUS\r
1323EFIAPI\r
1324EhcDriverBindingSupported (\r
1325 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1326 IN EFI_HANDLE Controller,\r
1327 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1328 )\r
1329{\r
1330 EFI_STATUS Status;\r
1331 EFI_PCI_IO_PROTOCOL *PciIo;\r
1332 USB_CLASSC UsbClassCReg;\r
1333\r
1334 //\r
1335 // Test whether there is PCI IO Protocol attached on the controller handle.\r
1336 //\r
1337 Status = gBS->OpenProtocol (\r
1338 Controller,\r
1339 &gEfiPciIoProtocolGuid,\r
c52fa98c 1340 (VOID **) &PciIo,\r
913cb9dc 1341 This->DriverBindingHandle,\r
1342 Controller,\r
1343 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1344 );\r
1345\r
1346 if (EFI_ERROR (Status)) {\r
1347 return EFI_UNSUPPORTED;\r
1348 }\r
1349\r
1350 Status = PciIo->Pci.Read (\r
1351 PciIo,\r
1352 EfiPciIoWidthUint8,\r
1353 EHC_PCI_CLASSC,\r
1354 sizeof (USB_CLASSC) / sizeof (UINT8),\r
1355 &UsbClassCReg\r
1356 );\r
1357\r
1358 if (EFI_ERROR (Status)) {\r
1359 Status = EFI_UNSUPPORTED;\r
1360 goto ON_EXIT;\r
1361 }\r
1362\r
1363 //\r
1364 // Test whether the controller belongs to Ehci type\r
1365 //\r
1366 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
1367 (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
1368 (UsbClassCReg.PI != EHC_PCI_CLASSC_PI)) {\r
1369\r
1370 Status = EFI_UNSUPPORTED;\r
1371 }\r
1372\r
1373ON_EXIT:\r
1374 gBS->CloseProtocol (\r
1375 Controller,\r
1376 &gEfiPciIoProtocolGuid,\r
1377 This->DriverBindingHandle,\r
1378 Controller\r
1379 );\r
1380\r
1381 return Status;\r
1382}\r
1383\r
1384\r
1385/**\r
1386 Create and initialize a USB2_HC_DEV\r
1387\r
1388 @param PciIo The PciIo on this device\r
1389\r
1390 @return The allocated and initialized USB2_HC_DEV structure\r
1391 @return if created, otherwise NULL.\r
1392\r
1393**/\r
1394STATIC\r
1395USB2_HC_DEV *\r
1396EhcCreateUsb2Hc (\r
1397 IN EFI_PCI_IO_PROTOCOL *PciIo\r
1398 )\r
1399{\r
1400 USB2_HC_DEV *Ehc;\r
1401 EFI_STATUS Status;\r
1402\r
1403 Ehc = AllocateZeroPool (sizeof (USB2_HC_DEV));\r
1404\r
1405 if (Ehc == NULL) {\r
1406 return NULL;\r
1407 }\r
1408\r
1409 //\r
1410 // Init EFI_USB2_HC_PROTOCOL interface and private data structure\r
1411 //\r
1412 Ehc->Signature = USB2_HC_DEV_SIGNATURE;\r
1413\r
1414 Ehc->Usb2Hc.GetCapability = EhcGetCapability;\r
1415 Ehc->Usb2Hc.Reset = EhcReset;\r
1416 Ehc->Usb2Hc.GetState = EhcGetState;\r
1417 Ehc->Usb2Hc.SetState = EhcSetState;\r
1418 Ehc->Usb2Hc.ControlTransfer = EhcControlTransfer;\r
1419 Ehc->Usb2Hc.BulkTransfer = EhcBulkTransfer;\r
1420 Ehc->Usb2Hc.AsyncInterruptTransfer = EhcAsyncInterruptTransfer;\r
1421 Ehc->Usb2Hc.SyncInterruptTransfer = EhcSyncInterruptTransfer;\r
1422 Ehc->Usb2Hc.IsochronousTransfer = EhcIsochronousTransfer;\r
1423 Ehc->Usb2Hc.AsyncIsochronousTransfer = EhcAsyncIsochronousTransfer;\r
1424 Ehc->Usb2Hc.GetRootHubPortStatus = EhcGetRootHubPortStatus;\r
1425 Ehc->Usb2Hc.SetRootHubPortFeature = EhcSetRootHubPortFeature;\r
1426 Ehc->Usb2Hc.ClearRootHubPortFeature = EhcClearRootHubPortFeature;\r
1427 Ehc->Usb2Hc.MajorRevision = 0x1;\r
1428 Ehc->Usb2Hc.MinorRevision = 0x1;\r
1429\r
1430 Ehc->PciIo = PciIo;\r
1431\r
1432 InitializeListHead (&Ehc->AsyncIntTransfers);\r
1433\r
1434 Ehc->HcStructParams = EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET);\r
1435 Ehc->HcCapParams = EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET);\r
1436 Ehc->CapLen = EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET) & 0x0FF;\r
1437\r
1438 EHC_DEBUG (("EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen));\r
1439\r
1440 //\r
1441 // Create AsyncRequest Polling Timer\r
1442 //\r
1443 Status = gBS->CreateEvent (\r
1444 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
1445 TPL_CALLBACK,\r
1446 EhcMoniteAsyncRequests,\r
1447 Ehc,\r
1448 &Ehc->PollTimer\r
1449 );\r
1450\r
1451 if (EFI_ERROR (Status)) {\r
1452 gBS->FreePool (Ehc);\r
1453 return NULL;\r
1454 }\r
1455\r
1456 return Ehc;\r
1457}\r
1458\r
1459\r
1460/**\r
1461 Starting the Usb EHCI Driver\r
1462\r
1463 @param This Protocol instance pointer.\r
1464 @param Controller Handle of device to test\r
1465 @param RemainingDevicePath Not used\r
1466\r
1467 @return EFI_SUCCESS : supports this device.\r
1468 @return EFI_UNSUPPORTED : do not support this device.\r
1469 @return EFI_DEVICE_ERROR : cannot be started due to device Error\r
1470 @return EFI_OUT_OF_RESOURCES : cannot allocate resources\r
1471\r
1472**/\r
1473EFI_STATUS\r
1474EFIAPI\r
1475EhcDriverBindingStart (\r
1476 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1477 IN EFI_HANDLE Controller,\r
1478 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1479 )\r
1480{\r
1481 EFI_STATUS Status;\r
1482 USB2_HC_DEV *Ehc;\r
1483 EFI_PCI_IO_PROTOCOL *PciIo;\r
1484\r
1485 //\r
1486 // Open the PciIo Protocol, then enable the USB host controller\r
1487 //\r
1488 Status = gBS->OpenProtocol (\r
1489 Controller,\r
1490 &gEfiPciIoProtocolGuid,\r
c52fa98c 1491 (VOID **) &PciIo,\r
913cb9dc 1492 This->DriverBindingHandle,\r
1493 Controller,\r
1494 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1495 );\r
1496\r
1497 if (EFI_ERROR (Status)) {\r
1498 EHC_ERROR (("EhcDriverBindingStart: failed to open PCI_IO\n"));\r
1499 return EFI_DEVICE_ERROR;\r
1500 }\r
1501\r
1502 Status = PciIo->Attributes (\r
1503 PciIo,\r
1504 EfiPciIoAttributeOperationEnable,\r
1505 EFI_PCI_DEVICE_ENABLE,\r
1506 NULL\r
1507 );\r
1508\r
1509 if (EFI_ERROR (Status)) {\r
1510 EHC_ERROR (("EhcDriverBindingStart: failed to enable controller\n"));\r
1511 goto CLOSE_PCIIO;\r
1512 }\r
1513\r
1514 //\r
1515 // Create then install USB2_HC_PROTOCOL\r
1516 //\r
1517 Ehc = EhcCreateUsb2Hc (PciIo);\r
1518\r
1519 if (Ehc == NULL) {\r
1520 EHC_ERROR (("EhcDriverBindingStart: failed to create USB2_HC\n"));\r
1521\r
1522 Status = EFI_OUT_OF_RESOURCES;\r
1523 goto CLOSE_PCIIO;\r
1524 }\r
1525\r
1526 Status = gBS->InstallProtocolInterface (\r
1527 &Controller,\r
1528 &gEfiUsb2HcProtocolGuid,\r
1529 EFI_NATIVE_INTERFACE,\r
1530 &Ehc->Usb2Hc\r
1531 );\r
1532\r
1533 if (EFI_ERROR (Status)) {\r
1534 EHC_ERROR (("EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));\r
1535 goto FREE_POOL;\r
1536 }\r
1537\r
1538 //\r
1539 // Robustnesss improvement such as for UoL\r
1540 //\r
1541 EhcClearLegacySupport (Ehc);\r
1542 EhcResetHC (Ehc, EHC_STALL_1_SECOND);\r
1543\r
1544 Status = EhcInitHC (Ehc);\r
1545\r
1546 if (EFI_ERROR (Status)) {\r
1547 EHC_ERROR (("EhcDriverBindingStart: failed to init host controller\n"));\r
1548 goto UNINSTALL_USBHC;\r
1549 }\r
1550\r
1551 //\r
1552 // Start the asynchronous interrupt monitor\r
1553 //\r
1554 Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_TIME);\r
1555\r
1556 if (EFI_ERROR (Status)) {\r
1557 EHC_ERROR (("EhcDriverBindingStart: failed to start async interrupt monitor\n"));\r
1558\r
1559 EhcHaltHC (Ehc, EHC_GENERIC_TIME);\r
1560 goto UNINSTALL_USBHC;\r
1561 }\r
1562\r
1563 //\r
1564 // Install the component name protocol, don't fail the start\r
1565 // because of something for display.\r
1566 //\r
f527bce3 1567 AddUnicodeString2 (\r
913cb9dc 1568 "eng",\r
1569 gEhciComponentName.SupportedLanguages,\r
1570 &Ehc->ControllerNameTable,\r
f527bce3 1571 L"Enhanced Host Controller (USB 2.0)",\r
1572 TRUE\r
913cb9dc 1573 );\r
f527bce3 1574 AddUnicodeString2 (\r
1575 "en",\r
1576 gEhciComponentName2.SupportedLanguages,\r
1577 &Ehc->ControllerNameTable,\r
1578 L"Enhanced Host Controller (USB 2.0)",\r
1579 FALSE\r
1580 );\r
1581\r
913cb9dc 1582\r
1583 EHC_DEBUG (("EhcDriverBindingStart: EHCI started for controller @ %x\n", Controller));\r
1584 return EFI_SUCCESS;\r
1585\r
1586UNINSTALL_USBHC:\r
1587 gBS->UninstallProtocolInterface (\r
1588 Controller,\r
1589 &gEfiUsb2HcProtocolGuid,\r
1590 &Ehc->Usb2Hc\r
1591 );\r
1592\r
1593FREE_POOL:\r
1594 EhcFreeSched (Ehc);\r
1595 gBS->CloseEvent (Ehc->PollTimer);\r
1596 gBS->FreePool (Ehc);\r
1597\r
1598CLOSE_PCIIO:\r
1599 gBS->CloseProtocol (\r
1600 Controller,\r
1601 &gEfiPciIoProtocolGuid,\r
1602 This->DriverBindingHandle,\r
1603 Controller\r
1604 );\r
1605\r
1606 return Status;\r
1607}\r
1608\r
1609\r
1610/**\r
1611 Stop this driver on ControllerHandle. Support stoping any child handles\r
1612 created by this driver.\r
1613\r
1614 @param This Protocol instance pointer.\r
1615 @param Controller Handle of device to stop driver on\r
1616 @param NumberOfChildren Number of Children in the ChildHandleBuffer\r
1617 @param ChildHandleBuffer List of handles for the children we need to stop.\r
1618\r
1619 @return EFI_SUCCESS Success\r
1620 @return EFI_DEVICE_ERROR Fail\r
1621\r
1622**/\r
1623EFI_STATUS\r
1624EFIAPI\r
1625EhcDriverBindingStop (\r
1626 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1627 IN EFI_HANDLE Controller,\r
1628 IN UINTN NumberOfChildren,\r
1629 IN EFI_HANDLE *ChildHandleBuffer\r
1630 )\r
1631{\r
1632 EFI_STATUS Status;\r
1633 EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
1634 EFI_PCI_IO_PROTOCOL *PciIo;\r
1635 USB2_HC_DEV *Ehc;\r
1636\r
1637 //\r
1638 // Test whether the Controller handler passed in is a valid\r
1639 // Usb controller handle that should be supported, if not,\r
1640 // return the error status directly\r
1641 //\r
1642 Status = gBS->OpenProtocol (\r
1643 Controller,\r
1644 &gEfiUsb2HcProtocolGuid,\r
c52fa98c 1645 (VOID **) &Usb2Hc,\r
913cb9dc 1646 This->DriverBindingHandle,\r
1647 Controller,\r
1648 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1649 );\r
1650\r
1651 if (EFI_ERROR (Status)) {\r
1652 return Status;\r
1653 }\r
1654\r
1655 Ehc = EHC_FROM_THIS (Usb2Hc);\r
1656 PciIo = Ehc->PciIo;\r
1657\r
1658 //\r
1659 // Stop AsyncRequest Polling timer then stop the EHCI driver\r
1660 // and uninstall the EHCI protocl.\r
1661 //\r
1662 gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_TIME);\r
1663 EhcHaltHC (Ehc, EHC_GENERIC_TIME);\r
1664\r
1665 Status = gBS->UninstallProtocolInterface (\r
1666 Controller,\r
1667 &gEfiUsb2HcProtocolGuid,\r
1668 Usb2Hc\r
1669 );\r
1670\r
1671 if (EFI_ERROR (Status)) {\r
1672 return Status;\r
1673 }\r
1674\r
1675 if (Ehc->PollTimer != NULL) {\r
1676 gBS->CloseEvent (Ehc->PollTimer);\r
1677 }\r
1678\r
1679 EhcFreeSched (Ehc);\r
1680\r
1681 if (Ehc->ControllerNameTable) {\r
1682 FreeUnicodeStringTable (Ehc->ControllerNameTable);\r
1683 }\r
1684\r
1685 //\r
1686 // Disable the USB Host Controller\r
1687 //\r
1688 PciIo->Attributes (\r
1689 PciIo,\r
1690 EfiPciIoAttributeOperationDisable,\r
1691 EFI_PCI_DEVICE_ENABLE,\r
1692 NULL\r
1693 );\r
1694\r
1695 gBS->CloseProtocol (\r
1696 Controller,\r
1697 &gEfiPciIoProtocolGuid,\r
1698 This->DriverBindingHandle,\r
1699 Controller\r
1700 );\r
1701\r
1702 gBS->FreePool (Ehc);\r
1703 return Status;\r
1704}\r
1705\r
1706EFI_DRIVER_BINDING_PROTOCOL\r
1707gEhciDriverBinding = {\r
1708 EhcDriverBindingSupported,\r
1709 EhcDriverBindingStart,\r
1710 EhcDriverBindingStop,\r
1711 0x10,\r
1712 NULL,\r
1713 NULL\r
1714};\r