~ubuntu-branches/ubuntu/wily/edk2/wily

« back to all changes in this revision

Viewing changes to MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c

  • Committer: Package Import Robot
  • Author(s): Steve Langasek
  • Date: 2013-02-10 13:11:25 UTC
  • Revision ID: package-import@ubuntu.com-20130210131125-0zwkb8f8m4ecia4m
Tags: upstream-0~20121205.edae8d2d
ImportĀ upstreamĀ versionĀ 0~20121205.edae8d2d

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** @file  
 
2
  The Ehci controller driver.
 
3
 
 
4
  EhciDxe driver is responsible for managing the behavior of EHCI controller. 
 
5
  It implements the interfaces of monitoring the status of all ports and transferring 
 
6
  Control, Bulk, Interrupt and Isochronous requests to Usb2.0 device.
 
7
 
 
8
  Note that EhciDxe driver is enhanced to guarantee that the EHCI controller get attached
 
9
  to the EHCI controller before the UHCI driver attaches to the companion UHCI controller. 
 
10
  This way avoids the control transfer on a shared port between EHCI and companion host
 
11
  controller when UHCI gets attached earlier than EHCI and a USB 2.0 device inserts.
 
12
 
 
13
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
 
14
This program and the accompanying materials
 
15
are licensed and made available under the terms and conditions of the BSD License
 
16
which accompanies this distribution.  The full text of the license may be found at
 
17
http://opensource.org/licenses/bsd-license.php
 
18
 
 
19
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 
20
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
21
 
 
22
**/
 
23
 
 
24
 
 
25
#include "Ehci.h"
 
26
 
 
27
//
 
28
// Two arrays used to translate the EHCI port state (change)
 
29
// to the UEFI protocol's port state (change).
 
30
//
 
31
USB_PORT_STATE_MAP  mUsbPortStateMap[] = {
 
32
  {PORTSC_CONN,     USB_PORT_STAT_CONNECTION},
 
33
  {PORTSC_ENABLED,  USB_PORT_STAT_ENABLE},
 
34
  {PORTSC_SUSPEND,  USB_PORT_STAT_SUSPEND},
 
35
  {PORTSC_OVERCUR,  USB_PORT_STAT_OVERCURRENT},
 
36
  {PORTSC_RESET,    USB_PORT_STAT_RESET},
 
37
  {PORTSC_POWER,    USB_PORT_STAT_POWER},
 
38
  {PORTSC_OWNER,    USB_PORT_STAT_OWNER}
 
39
};
 
40
 
 
41
USB_PORT_STATE_MAP  mUsbPortChangeMap[] = {
 
42
  {PORTSC_CONN_CHANGE,    USB_PORT_STAT_C_CONNECTION},
 
43
  {PORTSC_ENABLE_CHANGE,  USB_PORT_STAT_C_ENABLE},
 
44
  {PORTSC_OVERCUR_CHANGE, USB_PORT_STAT_C_OVERCURRENT}
 
45
};
 
46
 
 
47
EFI_DRIVER_BINDING_PROTOCOL
 
48
gEhciDriverBinding = {
 
49
  EhcDriverBindingSupported,
 
50
  EhcDriverBindingStart,
 
51
  EhcDriverBindingStop,
 
52
  0x30,
 
53
  NULL,
 
54
  NULL
 
55
};
 
56
 
 
57
/**
 
58
  Retrieves the capability of root hub ports.
 
59
 
 
60
  @param  This                  This EFI_USB_HC_PROTOCOL instance.
 
61
  @param  MaxSpeed              Max speed supported by the controller.
 
62
  @param  PortNumber            Number of the root hub ports.
 
63
  @param  Is64BitCapable        Whether the controller supports 64-bit memory
 
64
                                addressing.
 
65
 
 
66
  @retval EFI_SUCCESS           Host controller capability were retrieved successfully.
 
67
  @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.
 
68
 
 
69
**/
 
70
EFI_STATUS
 
71
EFIAPI
 
72
EhcGetCapability (
 
73
  IN  EFI_USB2_HC_PROTOCOL  *This,
 
74
  OUT UINT8                 *MaxSpeed,
 
75
  OUT UINT8                 *PortNumber,
 
76
  OUT UINT8                 *Is64BitCapable
 
77
  )
 
78
{
 
79
  USB2_HC_DEV             *Ehc;
 
80
  EFI_TPL                 OldTpl;
 
81
 
 
82
  if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {
 
83
    return EFI_INVALID_PARAMETER;
 
84
  }
 
85
 
 
86
  OldTpl          = gBS->RaiseTPL (EHC_TPL);
 
87
  Ehc             = EHC_FROM_THIS (This);
 
88
 
 
89
  *MaxSpeed       = EFI_USB_SPEED_HIGH;
 
90
  *PortNumber     = (UINT8) (Ehc->HcStructParams & HCSP_NPORTS);
 
91
  *Is64BitCapable = (UINT8) (Ehc->HcCapParams & HCCP_64BIT);
 
92
 
 
93
  DEBUG ((EFI_D_INFO, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));
 
94
 
 
95
  gBS->RestoreTPL (OldTpl);
 
96
  return EFI_SUCCESS;
 
97
}
 
98
 
 
99
 
 
100
/**
 
101
  Provides software reset for the USB host controller.
 
102
 
 
103
  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
 
104
  @param  Attributes            A bit mask of the reset operation to perform.
 
105
 
 
106
  @retval EFI_SUCCESS           The reset operation succeeded.
 
107
  @retval EFI_INVALID_PARAMETER Attributes is not valid.
 
108
  @retval EFI_UNSUPPOURTED      The type of reset specified by Attributes is
 
109
                                not currently supported by the host controller.
 
110
  @retval EFI_DEVICE_ERROR      Host controller isn't halted to reset.
 
111
 
 
112
**/
 
113
EFI_STATUS
 
114
EFIAPI
 
115
EhcReset (
 
116
  IN EFI_USB2_HC_PROTOCOL *This,
 
117
  IN UINT16               Attributes
 
118
  )
 
119
{
 
120
  USB2_HC_DEV             *Ehc;
 
121
  EFI_TPL                 OldTpl;
 
122
  EFI_STATUS              Status;
 
123
  UINT32                  DbgCtrlStatus;
 
124
 
 
125
  Ehc = EHC_FROM_THIS (This);
 
126
 
 
127
  if (Ehc->DevicePath != NULL) {
 
128
    //
 
129
    // Report Status Code to indicate reset happens
 
130
    //
 
131
    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 
132
      EFI_PROGRESS_CODE,
 
133
      (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),
 
134
      Ehc->DevicePath
 
135
      );
 
136
  }
 
137
 
 
138
  OldTpl  = gBS->RaiseTPL (EHC_TPL);
 
139
 
 
140
  switch (Attributes) {
 
141
  case EFI_USB_HC_RESET_GLOBAL:
 
142
  //
 
143
  // Flow through, same behavior as Host Controller Reset
 
144
  //
 
145
  case EFI_USB_HC_RESET_HOST_CONTROLLER:
 
146
    //
 
147
    // Host Controller must be Halt when Reset it
 
148
    //
 
149
    if (Ehc->DebugPortNum != 0) {
 
150
      DbgCtrlStatus = EhcReadDbgRegister(Ehc, 0);
 
151
      if ((DbgCtrlStatus & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) == (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) {
 
152
        Status = EFI_SUCCESS;
 
153
        goto ON_EXIT;
 
154
      }
 
155
    }
 
156
 
 
157
    if (!EhcIsHalt (Ehc)) {
 
158
      Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
 
159
 
 
160
      if (EFI_ERROR (Status)) {
 
161
        Status = EFI_DEVICE_ERROR;
 
162
        goto ON_EXIT;
 
163
      }
 
164
    }
 
165
 
 
166
    //
 
167
    // Clean up the asynchronous transfers, currently only
 
168
    // interrupt supports asynchronous operation.
 
169
    //
 
170
    EhciDelAllAsyncIntTransfers (Ehc);
 
171
    EhcAckAllInterrupt (Ehc);
 
172
    EhcFreeSched (Ehc);
 
173
 
 
174
    Status = EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
 
175
 
 
176
    if (EFI_ERROR (Status)) {
 
177
      goto ON_EXIT;
 
178
    }
 
179
 
 
180
    Status = EhcInitHC (Ehc);
 
181
    break;
 
182
 
 
183
  case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:
 
184
  case EFI_USB_HC_RESET_HOST_WITH_DEBUG:
 
185
    Status = EFI_UNSUPPORTED;
 
186
    break;
 
187
 
 
188
  default:
 
189
    Status = EFI_INVALID_PARAMETER;
 
190
  }
 
191
 
 
192
ON_EXIT:
 
193
  DEBUG ((EFI_D_INFO, "EhcReset: exit status %r\n", Status));
 
194
  gBS->RestoreTPL (OldTpl);
 
195
  return Status;
 
196
}
 
197
 
 
198
 
 
199
/**
 
200
  Retrieve the current state of the USB host controller.
 
201
 
 
202
  @param  This                   This EFI_USB2_HC_PROTOCOL instance.
 
203
  @param  State                  Variable to return the current host controller
 
204
                                 state.
 
205
 
 
206
  @retval EFI_SUCCESS            Host controller state was returned in State.
 
207
  @retval EFI_INVALID_PARAMETER  State is NULL.
 
208
  @retval EFI_DEVICE_ERROR       An error was encountered while attempting to
 
209
                                 retrieve the host controller's current state.
 
210
 
 
211
**/
 
212
EFI_STATUS
 
213
EFIAPI
 
214
EhcGetState (
 
215
  IN   EFI_USB2_HC_PROTOCOL  *This,
 
216
  OUT  EFI_USB_HC_STATE      *State
 
217
  )
 
218
{
 
219
  EFI_TPL                 OldTpl;
 
220
  USB2_HC_DEV             *Ehc;
 
221
 
 
222
  if (State == NULL) {
 
223
    return EFI_INVALID_PARAMETER;
 
224
  }
 
225
 
 
226
  OldTpl  = gBS->RaiseTPL (EHC_TPL);
 
227
  Ehc     = EHC_FROM_THIS (This);
 
228
 
 
229
  if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
 
230
    *State = EfiUsbHcStateHalt;
 
231
  } else {
 
232
    *State = EfiUsbHcStateOperational;
 
233
  }
 
234
 
 
235
  gBS->RestoreTPL (OldTpl);
 
236
 
 
237
  DEBUG ((EFI_D_INFO, "EhcGetState: current state %d\n", *State));
 
238
  return EFI_SUCCESS;
 
239
}
 
240
 
 
241
 
 
242
/**
 
243
  Sets the USB host controller to a specific state.
 
244
 
 
245
  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
 
246
  @param  State                 The state of the host controller that will be set.
 
247
 
 
248
  @retval EFI_SUCCESS           The USB host controller was successfully placed
 
249
                                in the state specified by State.
 
250
  @retval EFI_INVALID_PARAMETER State is invalid.
 
251
  @retval EFI_DEVICE_ERROR      Failed to set the state due to device error.
 
252
 
 
253
**/
 
254
EFI_STATUS
 
255
EFIAPI
 
256
EhcSetState (
 
257
  IN EFI_USB2_HC_PROTOCOL *This,
 
258
  IN EFI_USB_HC_STATE     State
 
259
  )
 
260
{
 
261
  USB2_HC_DEV             *Ehc;
 
262
  EFI_TPL                 OldTpl;
 
263
  EFI_STATUS              Status;
 
264
  EFI_USB_HC_STATE        CurState;
 
265
 
 
266
  Status = EhcGetState (This, &CurState);
 
267
 
 
268
  if (EFI_ERROR (Status)) {
 
269
    return EFI_DEVICE_ERROR;
 
270
  }
 
271
 
 
272
  if (CurState == State) {
 
273
    return EFI_SUCCESS;
 
274
  }
 
275
 
 
276
  OldTpl  = gBS->RaiseTPL (EHC_TPL);
 
277
  Ehc     = EHC_FROM_THIS (This);
 
278
 
 
279
  switch (State) {
 
280
  case EfiUsbHcStateHalt:
 
281
    Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
 
282
    break;
 
283
 
 
284
  case EfiUsbHcStateOperational:
 
285
    if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR)) {
 
286
      Status = EFI_DEVICE_ERROR;
 
287
      break;
 
288
    }
 
289
 
 
290
    //
 
291
    // Software must not write a one to this field unless the host controller
 
292
    // is in the Halted state. Doing so will yield undefined results.
 
293
    // refers to Spec[EHCI1.0-2.3.1]
 
294
    //
 
295
    if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
 
296
      Status = EFI_DEVICE_ERROR;
 
297
      break;
 
298
    }
 
299
 
 
300
    Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
 
301
    break;
 
302
 
 
303
  case EfiUsbHcStateSuspend:
 
304
    Status = EFI_UNSUPPORTED;
 
305
    break;
 
306
 
 
307
  default:
 
308
    Status = EFI_INVALID_PARAMETER;
 
309
  }
 
310
 
 
311
  DEBUG ((EFI_D_INFO, "EhcSetState: exit status %r\n", Status));
 
312
  gBS->RestoreTPL (OldTpl);
 
313
  return Status;
 
314
}
 
315
 
 
316
 
 
317
/**
 
318
  Retrieves the current status of a USB root hub port.
 
319
 
 
320
  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
 
321
  @param  PortNumber            The root hub port to retrieve the state from.
 
322
                                This value is zero-based.
 
323
  @param  PortStatus            Variable to receive the port state.
 
324
 
 
325
  @retval EFI_SUCCESS           The status of the USB root hub port specified.
 
326
                                by PortNumber was returned in PortStatus.
 
327
  @retval EFI_INVALID_PARAMETER PortNumber is invalid.
 
328
  @retval EFI_DEVICE_ERROR      Can't read register.
 
329
 
 
330
**/
 
331
EFI_STATUS
 
332
EFIAPI
 
333
EhcGetRootHubPortStatus (
 
334
  IN   EFI_USB2_HC_PROTOCOL  *This,
 
335
  IN   UINT8                 PortNumber,
 
336
  OUT  EFI_USB_PORT_STATUS   *PortStatus
 
337
  )
 
338
{
 
339
  USB2_HC_DEV             *Ehc;
 
340
  EFI_TPL                 OldTpl;
 
341
  UINT32                  Offset;
 
342
  UINT32                  State;
 
343
  UINT32                  TotalPort;
 
344
  UINTN                   Index;
 
345
  UINTN                   MapSize;
 
346
  EFI_STATUS              Status;
 
347
  UINT32                  DbgCtrlStatus;
 
348
 
 
349
  if (PortStatus == NULL) {
 
350
    return EFI_INVALID_PARAMETER;
 
351
  }
 
352
 
 
353
  OldTpl    = gBS->RaiseTPL (EHC_TPL);
 
354
 
 
355
  Ehc       = EHC_FROM_THIS (This);
 
356
  Status    = EFI_SUCCESS;
 
357
 
 
358
  TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
 
359
 
 
360
  if (PortNumber >= TotalPort) {
 
361
    Status = EFI_INVALID_PARAMETER;
 
362
    goto ON_EXIT;
 
363
  }
 
364
 
 
365
  Offset                        = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
 
366
  PortStatus->PortStatus        = 0;
 
367
  PortStatus->PortChangeStatus  = 0;
 
368
 
 
369
  if ((Ehc->DebugPortNum != 0) && (PortNumber == (Ehc->DebugPortNum - 1))) {
 
370
    DbgCtrlStatus = EhcReadDbgRegister(Ehc, 0);
 
371
    if ((DbgCtrlStatus & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) == (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) {
 
372
      goto ON_EXIT;
 
373
    }
 
374
  }
 
375
 
 
376
  State                         = EhcReadOpReg (Ehc, Offset);
 
377
 
 
378
  //
 
379
  // Identify device speed. If in K state, it is low speed.
 
380
  // If the port is enabled after reset, the device is of
 
381
  // high speed. The USB bus driver should retrieve the actual
 
382
  // port speed after reset.
 
383
  //
 
384
  if (EHC_BIT_IS_SET (State, PORTSC_LINESTATE_K)) {
 
385
    PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
 
386
 
 
387
  } else if (EHC_BIT_IS_SET (State, PORTSC_ENABLED)) {
 
388
    PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
 
389
  }
 
390
 
 
391
  //
 
392
  // Convert the EHCI port/port change state to UEFI status
 
393
  //
 
394
  MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
 
395
 
 
396
  for (Index = 0; Index < MapSize; Index++) {
 
397
    if (EHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
 
398
      PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
 
399
    }
 
400
  }
 
401
 
 
402
  MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
 
403
 
 
404
  for (Index = 0; Index < MapSize; Index++) {
 
405
    if (EHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
 
406
      PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
 
407
    }
 
408
  }
 
409
 
 
410
ON_EXIT:
 
411
  gBS->RestoreTPL (OldTpl);
 
412
  return Status;
 
413
}
 
414
 
 
415
 
 
416
/**
 
417
  Sets a feature for the specified root hub port.
 
418
 
 
419
  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
 
420
  @param  PortNumber            Root hub port to set.
 
421
  @param  PortFeature           Feature to set.
 
422
 
 
423
  @retval EFI_SUCCESS           The feature specified by PortFeature was set.
 
424
  @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
 
425
  @retval EFI_DEVICE_ERROR      Can't read register.
 
426
 
 
427
**/
 
428
EFI_STATUS
 
429
EFIAPI
 
430
EhcSetRootHubPortFeature (
 
431
  IN  EFI_USB2_HC_PROTOCOL  *This,
 
432
  IN  UINT8                 PortNumber,
 
433
  IN  EFI_USB_PORT_FEATURE  PortFeature
 
434
  )
 
435
{
 
436
  USB2_HC_DEV             *Ehc;
 
437
  EFI_TPL                 OldTpl;
 
438
  UINT32                  Offset;
 
439
  UINT32                  State;
 
440
  UINT32                  TotalPort;
 
441
  EFI_STATUS              Status;
 
442
 
 
443
  OldTpl    = gBS->RaiseTPL (EHC_TPL);
 
444
  Ehc       = EHC_FROM_THIS (This);
 
445
  Status    = EFI_SUCCESS;
 
446
 
 
447
  TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
 
448
 
 
449
  if (PortNumber >= TotalPort) {
 
450
    Status = EFI_INVALID_PARAMETER;
 
451
    goto ON_EXIT;
 
452
  }
 
453
 
 
454
  Offset  = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
 
455
  State   = EhcReadOpReg (Ehc, Offset);
 
456
 
 
457
  //
 
458
  // Mask off the port status change bits, these bits are
 
459
  // write clean bit
 
460
  //
 
461
  State &= ~PORTSC_CHANGE_MASK;
 
462
 
 
463
  switch (PortFeature) {
 
464
  case EfiUsbPortEnable:
 
465
    //
 
466
    // Sofeware can't set this bit, Port can only be enable by
 
467
    // EHCI as a part of the reset and enable
 
468
    //
 
469
    State |= PORTSC_ENABLED;
 
470
    EhcWriteOpReg (Ehc, Offset, State);
 
471
    break;
 
472
 
 
473
  case EfiUsbPortSuspend:
 
474
    State |= PORTSC_SUSPEND;
 
475
    EhcWriteOpReg (Ehc, Offset, State);
 
476
    break;
 
477
 
 
478
  case EfiUsbPortReset:
 
479
    //
 
480
    // Make sure Host Controller not halt before reset it
 
481
    //
 
482
    if (EhcIsHalt (Ehc)) {
 
483
      Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
 
484
 
 
485
      if (EFI_ERROR (Status)) {
 
486
        DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status));
 
487
        break;
 
488
      }
 
489
    }
 
490
 
 
491
    //
 
492
    // Set one to PortReset bit must also set zero to PortEnable bit
 
493
    //
 
494
    State |= PORTSC_RESET;
 
495
    State &= ~PORTSC_ENABLED;
 
496
    EhcWriteOpReg (Ehc, Offset, State);
 
497
    break;
 
498
 
 
499
  case EfiUsbPortPower:
 
500
    //
 
501
    // Set port power bit when PPC is 1
 
502
    //
 
503
    if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) {
 
504
      State |= PORTSC_POWER;
 
505
      EhcWriteOpReg (Ehc, Offset, State);
 
506
    }
 
507
    break;
 
508
 
 
509
  case EfiUsbPortOwner:
 
510
    State |= PORTSC_OWNER;
 
511
    EhcWriteOpReg (Ehc, Offset, State);
 
512
    break;
 
513
 
 
514
  default:
 
515
    Status = EFI_INVALID_PARAMETER;
 
516
  }
 
517
 
 
518
ON_EXIT:
 
519
  DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature: exit status %r\n", Status));
 
520
 
 
521
  gBS->RestoreTPL (OldTpl);
 
522
  return Status;
 
523
}
 
524
 
 
525
 
 
526
/**
 
527
  Clears a feature for the specified root hub port.
 
528
 
 
529
  @param  This                  A pointer to the EFI_USB2_HC_PROTOCOL instance.
 
530
  @param  PortNumber            Specifies the root hub port whose feature is
 
531
                                requested to be cleared.
 
532
  @param  PortFeature           Indicates the feature selector associated with the
 
533
                                feature clear request.
 
534
 
 
535
  @retval EFI_SUCCESS           The feature specified by PortFeature was cleared
 
536
                                for the USB root hub port specified by PortNumber.
 
537
  @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
 
538
  @retval EFI_DEVICE_ERROR      Can't read register.
 
539
 
 
540
**/
 
541
EFI_STATUS
 
542
EFIAPI
 
543
EhcClearRootHubPortFeature (
 
544
  IN  EFI_USB2_HC_PROTOCOL  *This,
 
545
  IN  UINT8                 PortNumber,
 
546
  IN  EFI_USB_PORT_FEATURE  PortFeature
 
547
  )
 
548
{
 
549
  USB2_HC_DEV             *Ehc;
 
550
  EFI_TPL                 OldTpl;
 
551
  UINT32                  Offset;
 
552
  UINT32                  State;
 
553
  UINT32                  TotalPort;
 
554
  EFI_STATUS              Status;
 
555
 
 
556
  OldTpl    = gBS->RaiseTPL (EHC_TPL);
 
557
  Ehc       = EHC_FROM_THIS (This);
 
558
  Status    = EFI_SUCCESS;
 
559
 
 
560
  TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
 
561
 
 
562
  if (PortNumber >= TotalPort) {
 
563
    Status = EFI_INVALID_PARAMETER;
 
564
    goto ON_EXIT;
 
565
  }
 
566
 
 
567
  Offset  = EHC_PORT_STAT_OFFSET + (4 * PortNumber);
 
568
  State   = EhcReadOpReg (Ehc, Offset);
 
569
  State &= ~PORTSC_CHANGE_MASK;
 
570
 
 
571
  switch (PortFeature) {
 
572
  case EfiUsbPortEnable:
 
573
    //
 
574
    // Clear PORT_ENABLE feature means disable port.
 
575
    //
 
576
    State &= ~PORTSC_ENABLED;
 
577
    EhcWriteOpReg (Ehc, Offset, State);
 
578
    break;
 
579
 
 
580
  case EfiUsbPortSuspend:
 
581
    //
 
582
    // A write of zero to this bit is ignored by the host
 
583
    // controller. The host controller will unconditionally
 
584
    // set this bit to a zero when:
 
585
    //   1. software sets the Forct Port Resume bit to a zero from a one.
 
586
    //   2. software sets the Port Reset bit to a one frome a zero.
 
587
    //
 
588
    State &= ~PORSTSC_RESUME;
 
589
    EhcWriteOpReg (Ehc, Offset, State);
 
590
    break;
 
591
 
 
592
  case EfiUsbPortReset:
 
593
    //
 
594
    // Clear PORT_RESET means clear the reset signal.
 
595
    //
 
596
    State &= ~PORTSC_RESET;
 
597
    EhcWriteOpReg (Ehc, Offset, State);
 
598
    break;
 
599
 
 
600
  case EfiUsbPortOwner:
 
601
    //
 
602
    // Clear port owner means this port owned by EHC
 
603
    //
 
604
    State &= ~PORTSC_OWNER;
 
605
    EhcWriteOpReg (Ehc, Offset, State);
 
606
    break;
 
607
 
 
608
  case EfiUsbPortConnectChange:
 
609
    //
 
610
    // Clear connect status change
 
611
    //
 
612
    State |= PORTSC_CONN_CHANGE;
 
613
    EhcWriteOpReg (Ehc, Offset, State);
 
614
    break;
 
615
 
 
616
  case EfiUsbPortEnableChange:
 
617
    //
 
618
    // Clear enable status change
 
619
    //
 
620
    State |= PORTSC_ENABLE_CHANGE;
 
621
    EhcWriteOpReg (Ehc, Offset, State);
 
622
    break;
 
623
 
 
624
  case EfiUsbPortOverCurrentChange:
 
625
    //
 
626
    // Clear PortOverCurrent change
 
627
    //
 
628
    State |= PORTSC_OVERCUR_CHANGE;
 
629
    EhcWriteOpReg (Ehc, Offset, State);
 
630
    break;
 
631
 
 
632
  case EfiUsbPortPower:
 
633
    //
 
634
    // Clear port power bit when PPC is 1
 
635
    //
 
636
    if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) {
 
637
      State &= ~PORTSC_POWER;
 
638
      EhcWriteOpReg (Ehc, Offset, State);
 
639
    }
 
640
    break;
 
641
  case EfiUsbPortSuspendChange:
 
642
  case EfiUsbPortResetChange:
 
643
    //
 
644
    // Not supported or not related operation
 
645
    //
 
646
    break;
 
647
 
 
648
  default:
 
649
    Status = EFI_INVALID_PARAMETER;
 
650
    break;
 
651
  }
 
652
 
 
653
ON_EXIT:
 
654
  DEBUG ((EFI_D_INFO, "EhcClearRootHubPortFeature: exit status %r\n", Status));
 
655
  gBS->RestoreTPL (OldTpl);
 
656
  return Status;
 
657
}
 
658
 
 
659
 
 
660
/**
 
661
  Submits control transfer to a target USB device.
 
662
 
 
663
  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
 
664
  @param  DeviceAddress         The target device address.
 
665
  @param  DeviceSpeed           Target device speed.
 
666
  @param  MaximumPacketLength   Maximum packet size the default control transfer
 
667
                                endpoint is capable of sending or receiving.
 
668
  @param  Request               USB device request to send.
 
669
  @param  TransferDirection     Specifies the data direction for the data stage
 
670
  @param  Data                  Data buffer to be transmitted or received from USB
 
671
                                device.
 
672
  @param  DataLength            The size (in bytes) of the data buffer.
 
673
  @param  TimeOut               Indicates the maximum timeout, in millisecond.
 
674
  @param  Translator            Transaction translator to be used by this device.
 
675
  @param  TransferResult        Return the result of this control transfer.
 
676
 
 
677
  @retval EFI_SUCCESS           Transfer was completed successfully.
 
678
  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resources.
 
679
  @retval EFI_INVALID_PARAMETER Some parameters are invalid.
 
680
  @retval EFI_TIMEOUT           Transfer failed due to timeout.
 
681
  @retval EFI_DEVICE_ERROR      Transfer failed due to host controller or device error.
 
682
 
 
683
**/
 
684
EFI_STATUS
 
685
EFIAPI
 
686
EhcControlTransfer (
 
687
  IN  EFI_USB2_HC_PROTOCOL                *This,
 
688
  IN  UINT8                               DeviceAddress,
 
689
  IN  UINT8                               DeviceSpeed,
 
690
  IN  UINTN                               MaximumPacketLength,
 
691
  IN  EFI_USB_DEVICE_REQUEST              *Request,
 
692
  IN  EFI_USB_DATA_DIRECTION              TransferDirection,
 
693
  IN  OUT VOID                            *Data,
 
694
  IN  OUT UINTN                           *DataLength,
 
695
  IN  UINTN                               TimeOut,
 
696
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
 
697
  OUT UINT32                              *TransferResult
 
698
  )
 
699
{
 
700
  USB2_HC_DEV             *Ehc;
 
701
  URB                     *Urb;
 
702
  EFI_TPL                 OldTpl;
 
703
  UINT8                   Endpoint;
 
704
  EFI_STATUS              Status;
 
705
 
 
706
  //
 
707
  // Validate parameters
 
708
  //
 
709
  if ((Request == NULL) || (TransferResult == NULL)) {
 
710
    return EFI_INVALID_PARAMETER;
 
711
  }
 
712
 
 
713
  if ((TransferDirection != EfiUsbDataIn) &&
 
714
      (TransferDirection != EfiUsbDataOut) &&
 
715
      (TransferDirection != EfiUsbNoData)) {
 
716
    return EFI_INVALID_PARAMETER;
 
717
  }
 
718
 
 
719
  if ((TransferDirection == EfiUsbNoData) &&
 
720
      ((Data != NULL) || (*DataLength != 0))) {
 
721
    return EFI_INVALID_PARAMETER;
 
722
  }
 
723
 
 
724
  if ((TransferDirection != EfiUsbNoData) &&
 
725
     ((Data == NULL) || (*DataLength == 0))) {
 
726
    return EFI_INVALID_PARAMETER;
 
727
  }
 
728
 
 
729
  if ((MaximumPacketLength != 8)  && (MaximumPacketLength != 16) &&
 
730
      (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {
 
731
    return EFI_INVALID_PARAMETER;
 
732
  }
 
733
 
 
734
  if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {
 
735
    return EFI_INVALID_PARAMETER;
 
736
  }
 
737
 
 
738
  OldTpl          = gBS->RaiseTPL (EHC_TPL);
 
739
  Ehc             = EHC_FROM_THIS (This);
 
740
 
 
741
  Status          = EFI_DEVICE_ERROR;
 
742
  *TransferResult = EFI_USB_ERR_SYSTEM;
 
743
 
 
744
  if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
 
745
    DEBUG ((EFI_D_ERROR, "EhcControlTransfer: HC halted at entrance\n"));
 
746
 
 
747
    EhcAckAllInterrupt (Ehc);
 
748
    goto ON_EXIT;
 
749
  }
 
750
 
 
751
  EhcAckAllInterrupt (Ehc);
 
752
 
 
753
  //
 
754
  // Create a new URB, insert it into the asynchronous
 
755
  // schedule list, then poll the execution status.
 
756
  //
 
757
  //
 
758
  // Encode the direction in address, although default control
 
759
  // endpoint is bidirectional. EhcCreateUrb expects this
 
760
  // combination of Ep addr and its direction.
 
761
  //
 
762
  Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
 
763
  Urb = EhcCreateUrb (
 
764
          Ehc,
 
765
          DeviceAddress,
 
766
          Endpoint,
 
767
          DeviceSpeed,
 
768
          0,
 
769
          MaximumPacketLength,
 
770
          Translator,
 
771
          EHC_CTRL_TRANSFER,
 
772
          Request,
 
773
          Data,
 
774
          *DataLength,
 
775
          NULL,
 
776
          NULL,
 
777
          1
 
778
          );
 
779
 
 
780
  if (Urb == NULL) {
 
781
    DEBUG ((EFI_D_ERROR, "EhcControlTransfer: failed to create URB"));
 
782
 
 
783
    Status = EFI_OUT_OF_RESOURCES;
 
784
    goto ON_EXIT;
 
785
  }
 
786
 
 
787
  EhcLinkQhToAsync (Ehc, Urb->Qh);
 
788
  Status = EhcExecTransfer (Ehc, Urb, TimeOut);
 
789
  EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
 
790
 
 
791
  //
 
792
  // Get the status from URB. The result is updated in EhcCheckUrbResult
 
793
  // which is called by EhcExecTransfer
 
794
  //
 
795
  *TransferResult = Urb->Result;
 
796
  *DataLength     = Urb->Completed;
 
797
 
 
798
  if (*TransferResult == EFI_USB_NOERROR) {
 
799
    Status = EFI_SUCCESS;
 
800
  }
 
801
 
 
802
  EhcAckAllInterrupt (Ehc);
 
803
  EhcFreeUrb (Ehc, Urb);
 
804
 
 
805
ON_EXIT:
 
806
  Ehc->PciIo->Flush (Ehc->PciIo);
 
807
  gBS->RestoreTPL (OldTpl);
 
808
 
 
809
  if (EFI_ERROR (Status)) {
 
810
    DEBUG ((EFI_D_ERROR, "EhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
 
811
  }
 
812
 
 
813
  return Status;
 
814
}
 
815
 
 
816
 
 
817
/**
 
818
  Submits bulk transfer to a bulk endpoint of a USB device.
 
819
 
 
820
  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
 
821
  @param  DeviceAddress         Target device address.
 
822
  @param  EndPointAddress       Endpoint number and its direction in bit 7.
 
823
  @param  DeviceSpeed           Device speed, Low speed device doesn't support bulk
 
824
                                transfer.
 
825
  @param  MaximumPacketLength   Maximum packet size the endpoint is capable of
 
826
                                sending or receiving.
 
827
  @param  DataBuffersNumber     Number of data buffers prepared for the transfer.
 
828
  @param  Data                  Array of pointers to the buffers of data to transmit
 
829
                                from or receive into.
 
830
  @param  DataLength            The lenght of the data buffer.
 
831
  @param  DataToggle            On input, the initial data toggle for the transfer;
 
832
                                On output, it is updated to to next data toggle to
 
833
                                use of the subsequent bulk transfer.
 
834
  @param  TimeOut               Indicates the maximum time, in millisecond, which
 
835
                                the transfer is allowed to complete.
 
836
  @param  Translator            A pointr to the transaction translator data.
 
837
  @param  TransferResult        A pointer to the detailed result information of the
 
838
                                bulk transfer.
 
839
 
 
840
  @retval EFI_SUCCESS           The transfer was completed successfully.
 
841
  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
 
842
  @retval EFI_INVALID_PARAMETER Some parameters are invalid.
 
843
  @retval EFI_TIMEOUT           The transfer failed due to timeout.
 
844
  @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
 
845
 
 
846
**/
 
847
EFI_STATUS
 
848
EFIAPI
 
849
EhcBulkTransfer (
 
850
  IN  EFI_USB2_HC_PROTOCOL                *This,
 
851
  IN  UINT8                               DeviceAddress,
 
852
  IN  UINT8                               EndPointAddress,
 
853
  IN  UINT8                               DeviceSpeed,
 
854
  IN  UINTN                               MaximumPacketLength,
 
855
  IN  UINT8                               DataBuffersNumber,
 
856
  IN  OUT VOID                            *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
 
857
  IN  OUT UINTN                           *DataLength,
 
858
  IN  OUT UINT8                           *DataToggle,
 
859
  IN  UINTN                               TimeOut,
 
860
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
 
861
  OUT UINT32                              *TransferResult
 
862
  )
 
863
{
 
864
  USB2_HC_DEV             *Ehc;
 
865
  URB                     *Urb;
 
866
  EFI_TPL                 OldTpl;
 
867
  EFI_STATUS              Status;
 
868
 
 
869
  //
 
870
  // Validate the parameters
 
871
  //
 
872
  if ((DataLength == NULL) || (*DataLength == 0) ||
 
873
      (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {
 
874
    return EFI_INVALID_PARAMETER;
 
875
  }
 
876
 
 
877
  if ((*DataToggle != 0) && (*DataToggle != 1)) {
 
878
    return EFI_INVALID_PARAMETER;
 
879
  }
 
880
 
 
881
  if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
 
882
      ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
 
883
      ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) {
 
884
    return EFI_INVALID_PARAMETER;
 
885
  }
 
886
 
 
887
  OldTpl          = gBS->RaiseTPL (EHC_TPL);
 
888
  Ehc             = EHC_FROM_THIS (This);
 
889
 
 
890
  *TransferResult = EFI_USB_ERR_SYSTEM;
 
891
  Status          = EFI_DEVICE_ERROR;
 
892
 
 
893
  if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
 
894
    DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: HC is halted\n"));
 
895
 
 
896
    EhcAckAllInterrupt (Ehc);
 
897
    goto ON_EXIT;
 
898
  }
 
899
 
 
900
  EhcAckAllInterrupt (Ehc);
 
901
 
 
902
  //
 
903
  // Create a new URB, insert it into the asynchronous
 
904
  // schedule list, then poll the execution status.
 
905
  //
 
906
  Urb = EhcCreateUrb (
 
907
          Ehc,
 
908
          DeviceAddress,
 
909
          EndPointAddress,
 
910
          DeviceSpeed,
 
911
          *DataToggle,
 
912
          MaximumPacketLength,
 
913
          Translator,
 
914
          EHC_BULK_TRANSFER,
 
915
          NULL,
 
916
          Data[0],
 
917
          *DataLength,
 
918
          NULL,
 
919
          NULL,
 
920
          1
 
921
          );
 
922
 
 
923
  if (Urb == NULL) {
 
924
    DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: failed to create URB\n"));
 
925
 
 
926
    Status = EFI_OUT_OF_RESOURCES;
 
927
    goto ON_EXIT;
 
928
  }
 
929
 
 
930
  EhcLinkQhToAsync (Ehc, Urb->Qh);
 
931
  Status = EhcExecTransfer (Ehc, Urb, TimeOut);
 
932
  EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
 
933
 
 
934
  *TransferResult = Urb->Result;
 
935
  *DataLength     = Urb->Completed;
 
936
  *DataToggle     = Urb->DataToggle;
 
937
 
 
938
  if (*TransferResult == EFI_USB_NOERROR) {
 
939
    Status = EFI_SUCCESS;
 
940
  }
 
941
 
 
942
  EhcAckAllInterrupt (Ehc);
 
943
  EhcFreeUrb (Ehc, Urb);
 
944
 
 
945
ON_EXIT:
 
946
  Ehc->PciIo->Flush (Ehc->PciIo);
 
947
  gBS->RestoreTPL (OldTpl);
 
948
 
 
949
  if (EFI_ERROR (Status)) {
 
950
    DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
 
951
  }
 
952
 
 
953
  return Status;
 
954
}
 
955
 
 
956
 
 
957
/**
 
958
  Submits an asynchronous interrupt transfer to an
 
959
  interrupt endpoint of a USB device.
 
960
 
 
961
  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
 
962
  @param  DeviceAddress         Target device address.
 
963
  @param  EndPointAddress       Endpoint number and its direction encoded in bit 7
 
964
  @param  DeviceSpeed           Indicates device speed.
 
965
  @param  MaximumPacketLength   Maximum packet size the target endpoint is capable
 
966
  @param  IsNewTransfer         If TRUE, to submit an new asynchronous interrupt
 
967
                                transfer If FALSE, to remove the specified
 
968
                                asynchronous interrupt.
 
969
  @param  DataToggle            On input, the initial data toggle to use; on output,
 
970
                                it is updated to indicate the next data toggle.
 
971
  @param  PollingInterval       The he interval, in milliseconds, that the transfer
 
972
                                is polled.
 
973
  @param  DataLength            The length of data to receive at the rate specified
 
974
                                by  PollingInterval.
 
975
  @param  Translator            Transaction translator to use.
 
976
  @param  CallBackFunction      Function to call at the rate specified by
 
977
                                PollingInterval.
 
978
  @param  Context               Context to CallBackFunction.
 
979
 
 
980
  @retval EFI_SUCCESS           The request has been successfully submitted or canceled.
 
981
  @retval EFI_INVALID_PARAMETER Some parameters are invalid.
 
982
  @retval EFI_OUT_OF_RESOURCES  The request failed due to a lack of resources.
 
983
  @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
 
984
 
 
985
**/
 
986
EFI_STATUS
 
987
EFIAPI
 
988
EhcAsyncInterruptTransfer (
 
989
  IN  EFI_USB2_HC_PROTOCOL                  * This,
 
990
  IN  UINT8                                 DeviceAddress,
 
991
  IN  UINT8                                 EndPointAddress,
 
992
  IN  UINT8                                 DeviceSpeed,
 
993
  IN  UINTN                                 MaximumPacketLength,
 
994
  IN  BOOLEAN                               IsNewTransfer,
 
995
  IN  OUT UINT8                             *DataToggle,
 
996
  IN  UINTN                                 PollingInterval,
 
997
  IN  UINTN                                 DataLength,
 
998
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    * Translator,
 
999
  IN  EFI_ASYNC_USB_TRANSFER_CALLBACK       CallBackFunction,
 
1000
  IN  VOID                                  *Context OPTIONAL
 
1001
  )
 
1002
{
 
1003
  USB2_HC_DEV             *Ehc;
 
1004
  URB                     *Urb;
 
1005
  EFI_TPL                 OldTpl;
 
1006
  EFI_STATUS              Status;
 
1007
  UINT8                   *Data;
 
1008
 
 
1009
  //
 
1010
  // Validate parameters
 
1011
  //
 
1012
  if (!EHCI_IS_DATAIN (EndPointAddress)) {
 
1013
    return EFI_INVALID_PARAMETER;
 
1014
  }
 
1015
 
 
1016
  if (IsNewTransfer) {
 
1017
    if (DataLength == 0) {
 
1018
      return EFI_INVALID_PARAMETER;
 
1019
    }
 
1020
 
 
1021
    if ((*DataToggle != 1) && (*DataToggle != 0)) {
 
1022
      return EFI_INVALID_PARAMETER;
 
1023
    }
 
1024
 
 
1025
    if ((PollingInterval > 255) || (PollingInterval < 1)) {
 
1026
      return EFI_INVALID_PARAMETER;
 
1027
    }
 
1028
  }
 
1029
 
 
1030
  OldTpl  = gBS->RaiseTPL (EHC_TPL);
 
1031
  Ehc     = EHC_FROM_THIS (This);
 
1032
 
 
1033
  //
 
1034
  // Delete Async interrupt transfer request. DataToggle will return
 
1035
  // the next data toggle to use.
 
1036
  //
 
1037
  if (!IsNewTransfer) {
 
1038
    Status = EhciDelAsyncIntTransfer (Ehc, DeviceAddress, EndPointAddress, DataToggle);
 
1039
 
 
1040
    DEBUG ((EFI_D_INFO, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status));
 
1041
    goto ON_EXIT;
 
1042
  }
 
1043
 
 
1044
  Status = EFI_SUCCESS;
 
1045
 
 
1046
  if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
 
1047
    DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: HC is halt\n"));
 
1048
    EhcAckAllInterrupt (Ehc);
 
1049
 
 
1050
    Status = EFI_DEVICE_ERROR;
 
1051
    goto ON_EXIT;
 
1052
  }
 
1053
 
 
1054
  EhcAckAllInterrupt (Ehc);
 
1055
 
 
1056
  Data = AllocatePool (DataLength);
 
1057
 
 
1058
  if (Data == NULL) {
 
1059
    DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: failed to allocate buffer\n"));
 
1060
 
 
1061
    Status = EFI_OUT_OF_RESOURCES;
 
1062
    goto ON_EXIT;
 
1063
  }
 
1064
 
 
1065
  Urb = EhcCreateUrb (
 
1066
          Ehc,
 
1067
          DeviceAddress,
 
1068
          EndPointAddress,
 
1069
          DeviceSpeed,
 
1070
          *DataToggle,
 
1071
          MaximumPacketLength,
 
1072
          Translator,
 
1073
          EHC_INT_TRANSFER_ASYNC,
 
1074
          NULL,
 
1075
          Data,
 
1076
          DataLength,
 
1077
          CallBackFunction,
 
1078
          Context,
 
1079
          PollingInterval
 
1080
          );
 
1081
 
 
1082
  if (Urb == NULL) {
 
1083
    DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: failed to create URB\n"));
 
1084
 
 
1085
    gBS->FreePool (Data);
 
1086
    Status = EFI_OUT_OF_RESOURCES;
 
1087
    goto ON_EXIT;
 
1088
  }
 
1089
 
 
1090
  //
 
1091
  // New asynchronous transfer must inserted to the head.
 
1092
  // Check the comments in EhcMoniteAsyncRequests
 
1093
  //
 
1094
  EhcLinkQhToPeriod (Ehc, Urb->Qh);
 
1095
  InsertHeadList (&Ehc->AsyncIntTransfers, &Urb->UrbList);
 
1096
 
 
1097
ON_EXIT:
 
1098
  Ehc->PciIo->Flush (Ehc->PciIo);
 
1099
  gBS->RestoreTPL (OldTpl);
 
1100
 
 
1101
  return Status;
 
1102
}
 
1103
 
 
1104
 
 
1105
/**
 
1106
  Submits synchronous interrupt transfer to an interrupt endpoint
 
1107
  of a USB device.
 
1108
 
 
1109
  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
 
1110
  @param  DeviceAddress         Target device address.
 
1111
  @param  EndPointAddress       Endpoint number and its direction encoded in bit 7
 
1112
  @param  DeviceSpeed           Indicates device speed.
 
1113
  @param  MaximumPacketLength   Maximum packet size the target endpoint is capable
 
1114
                                of sending or receiving.
 
1115
  @param  Data                  Buffer of data that will be transmitted to  USB
 
1116
                                device or received from USB device.
 
1117
  @param  DataLength            On input, the size, in bytes, of the data buffer; On
 
1118
                                output, the number of bytes transferred.
 
1119
  @param  DataToggle            On input, the initial data toggle to use; on output,
 
1120
                                it is updated to indicate the next data toggle.
 
1121
  @param  TimeOut               Maximum time, in second, to complete.
 
1122
  @param  Translator            Transaction translator to use.
 
1123
  @param  TransferResult        Variable to receive the transfer result.
 
1124
 
 
1125
  @return EFI_SUCCESS           The transfer was completed successfully.
 
1126
  @return EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
 
1127
  @return EFI_INVALID_PARAMETER Some parameters are invalid.
 
1128
  @return EFI_TIMEOUT           The transfer failed due to timeout.
 
1129
  @return EFI_DEVICE_ERROR      The failed due to host controller or device error
 
1130
 
 
1131
**/
 
1132
EFI_STATUS
 
1133
EFIAPI
 
1134
EhcSyncInterruptTransfer (
 
1135
  IN  EFI_USB2_HC_PROTOCOL                *This,
 
1136
  IN  UINT8                               DeviceAddress,
 
1137
  IN  UINT8                               EndPointAddress,
 
1138
  IN  UINT8                               DeviceSpeed,
 
1139
  IN  UINTN                               MaximumPacketLength,
 
1140
  IN  OUT VOID                            *Data,
 
1141
  IN  OUT UINTN                           *DataLength,
 
1142
  IN  OUT UINT8                           *DataToggle,
 
1143
  IN  UINTN                               TimeOut,
 
1144
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
 
1145
  OUT UINT32                              *TransferResult
 
1146
  )
 
1147
{
 
1148
  USB2_HC_DEV             *Ehc;
 
1149
  EFI_TPL                 OldTpl;
 
1150
  URB                     *Urb;
 
1151
  EFI_STATUS              Status;
 
1152
 
 
1153
  //
 
1154
  // Validates parameters
 
1155
  //
 
1156
  if ((DataLength == NULL) || (*DataLength == 0) ||
 
1157
      (Data == NULL) || (TransferResult == NULL)) {
 
1158
    return EFI_INVALID_PARAMETER;
 
1159
  }
 
1160
 
 
1161
  if (!EHCI_IS_DATAIN (EndPointAddress)) {
 
1162
    return EFI_INVALID_PARAMETER;
 
1163
  }
 
1164
 
 
1165
  if ((*DataToggle != 1) && (*DataToggle != 0)) {
 
1166
    return EFI_INVALID_PARAMETER;
 
1167
  }
 
1168
 
 
1169
  if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8))  ||
 
1170
      ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
 
1171
      ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) {
 
1172
    return EFI_INVALID_PARAMETER;
 
1173
  }
 
1174
 
 
1175
  OldTpl          = gBS->RaiseTPL (EHC_TPL);
 
1176
  Ehc             = EHC_FROM_THIS (This);
 
1177
 
 
1178
  *TransferResult = EFI_USB_ERR_SYSTEM;
 
1179
  Status          = EFI_DEVICE_ERROR;
 
1180
 
 
1181
  if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
 
1182
    DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));
 
1183
 
 
1184
    EhcAckAllInterrupt (Ehc);
 
1185
    goto ON_EXIT;
 
1186
  }
 
1187
 
 
1188
  EhcAckAllInterrupt (Ehc);
 
1189
 
 
1190
  Urb = EhcCreateUrb (
 
1191
          Ehc,
 
1192
          DeviceAddress,
 
1193
          EndPointAddress,
 
1194
          DeviceSpeed,
 
1195
          *DataToggle,
 
1196
          MaximumPacketLength,
 
1197
          Translator,
 
1198
          EHC_INT_TRANSFER_SYNC,
 
1199
          NULL,
 
1200
          Data,
 
1201
          *DataLength,
 
1202
          NULL,
 
1203
          NULL,
 
1204
          1
 
1205
          );
 
1206
 
 
1207
  if (Urb == NULL) {
 
1208
    DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: failed to create URB\n"));
 
1209
 
 
1210
    Status = EFI_OUT_OF_RESOURCES;
 
1211
    goto ON_EXIT;
 
1212
  }
 
1213
 
 
1214
  EhcLinkQhToPeriod (Ehc, Urb->Qh);
 
1215
  Status = EhcExecTransfer (Ehc, Urb, TimeOut);
 
1216
  EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);
 
1217
 
 
1218
  *TransferResult = Urb->Result;
 
1219
  *DataLength     = Urb->Completed;
 
1220
  *DataToggle     = Urb->DataToggle;
 
1221
 
 
1222
  if (*TransferResult == EFI_USB_NOERROR) {
 
1223
    Status = EFI_SUCCESS;
 
1224
  }
 
1225
 
 
1226
ON_EXIT:
 
1227
  Ehc->PciIo->Flush (Ehc->PciIo);
 
1228
  gBS->RestoreTPL (OldTpl);
 
1229
 
 
1230
  if (EFI_ERROR (Status)) {
 
1231
    DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
 
1232
  }
 
1233
 
 
1234
  return Status;
 
1235
}
 
1236
 
 
1237
 
 
1238
/**
 
1239
  Submits isochronous transfer to a target USB device.
 
1240
 
 
1241
  @param  This                 This EFI_USB2_HC_PROTOCOL instance.
 
1242
  @param  DeviceAddress        Target device address.
 
1243
  @param  EndPointAddress      End point address with its direction.
 
1244
  @param  DeviceSpeed          Device speed, Low speed device doesn't support this
 
1245
                               type.
 
1246
  @param  MaximumPacketLength  Maximum packet size that the endpoint is capable of
 
1247
                               sending or receiving.
 
1248
  @param  DataBuffersNumber    Number of data buffers prepared for the transfer.
 
1249
  @param  Data                 Array of pointers to the buffers of data that will
 
1250
                               be transmitted to USB device or received from USB
 
1251
                               device.
 
1252
  @param  DataLength           The size, in bytes, of the data buffer.
 
1253
  @param  Translator           Transaction translator to use.
 
1254
  @param  TransferResult       Variable to receive the transfer result.
 
1255
 
 
1256
  @return EFI_UNSUPPORTED      Isochronous transfer is unsupported.
 
1257
 
 
1258
**/
 
1259
EFI_STATUS
 
1260
EFIAPI
 
1261
EhcIsochronousTransfer (
 
1262
  IN  EFI_USB2_HC_PROTOCOL                *This,
 
1263
  IN  UINT8                               DeviceAddress,
 
1264
  IN  UINT8                               EndPointAddress,
 
1265
  IN  UINT8                               DeviceSpeed,
 
1266
  IN  UINTN                               MaximumPacketLength,
 
1267
  IN  UINT8                               DataBuffersNumber,
 
1268
  IN  OUT VOID                            *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
 
1269
  IN  UINTN                               DataLength,
 
1270
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
 
1271
  OUT UINT32                              *TransferResult
 
1272
  )
 
1273
{
 
1274
  return EFI_UNSUPPORTED;
 
1275
}
 
1276
 
 
1277
 
 
1278
/**
 
1279
  Submits Async isochronous transfer to a target USB device.
 
1280
 
 
1281
  @param  This                 This EFI_USB2_HC_PROTOCOL instance.
 
1282
  @param  DeviceAddress        Target device address.
 
1283
  @param  EndPointAddress      End point address with its direction.
 
1284
  @param  DeviceSpeed          Device speed, Low speed device doesn't support this
 
1285
                               type.
 
1286
  @param  MaximumPacketLength  Maximum packet size that the endpoint is capable of
 
1287
                               sending or receiving.
 
1288
  @param  DataBuffersNumber    Number of data buffers prepared for the transfer.
 
1289
  @param  Data                 Array of pointers to the buffers of data that will
 
1290
                               be transmitted to USB device or received from USB
 
1291
                               device.
 
1292
  @param  DataLength           The size, in bytes, of the data buffer.
 
1293
  @param  Translator           Transaction translator to use.
 
1294
  @param  IsochronousCallBack  Function to be called when the transfer complete.
 
1295
  @param  Context              Context passed to the call back function as
 
1296
                               parameter.
 
1297
 
 
1298
  @return EFI_UNSUPPORTED      Isochronous transfer isn't supported.
 
1299
 
 
1300
**/
 
1301
EFI_STATUS
 
1302
EFIAPI
 
1303
EhcAsyncIsochronousTransfer (
 
1304
  IN  EFI_USB2_HC_PROTOCOL                *This,
 
1305
  IN  UINT8                               DeviceAddress,
 
1306
  IN  UINT8                               EndPointAddress,
 
1307
  IN  UINT8                               DeviceSpeed,
 
1308
  IN  UINTN                               MaximumPacketLength,
 
1309
  IN  UINT8                               DataBuffersNumber,
 
1310
  IN  OUT VOID                            *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
 
1311
  IN  UINTN                               DataLength,
 
1312
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
 
1313
  IN  EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,
 
1314
  IN  VOID                                *Context
 
1315
  )
 
1316
{
 
1317
  return EFI_UNSUPPORTED;
 
1318
}
 
1319
 
 
1320
/**
 
1321
  Entry point for EFI drivers.
 
1322
 
 
1323
  @param  ImageHandle       EFI_HANDLE.
 
1324
  @param  SystemTable       EFI_SYSTEM_TABLE.
 
1325
 
 
1326
  @return EFI_SUCCESS       Success.
 
1327
          EFI_DEVICE_ERROR  Fail.
 
1328
 
 
1329
**/
 
1330
EFI_STATUS
 
1331
EFIAPI
 
1332
EhcDriverEntryPoint (
 
1333
  IN EFI_HANDLE           ImageHandle,
 
1334
  IN EFI_SYSTEM_TABLE     *SystemTable
 
1335
  )
 
1336
{
 
1337
  return EfiLibInstallDriverBindingComponentName2 (
 
1338
           ImageHandle,
 
1339
           SystemTable,
 
1340
           &gEhciDriverBinding,
 
1341
           ImageHandle,
 
1342
           &gEhciComponentName,
 
1343
           &gEhciComponentName2
 
1344
           );
 
1345
}
 
1346
 
 
1347
 
 
1348
/**
 
1349
  Test to see if this driver supports ControllerHandle. Any
 
1350
  ControllerHandle that has Usb2HcProtocol installed will
 
1351
  be supported.
 
1352
 
 
1353
  @param  This                 Protocol instance pointer.
 
1354
  @param  Controller           Handle of device to test.
 
1355
  @param  RemainingDevicePath  Not used.
 
1356
 
 
1357
  @return EFI_SUCCESS          This driver supports this device.
 
1358
  @return EFI_UNSUPPORTED      This driver does not support this device.
 
1359
 
 
1360
**/
 
1361
EFI_STATUS
 
1362
EFIAPI
 
1363
EhcDriverBindingSupported (
 
1364
  IN EFI_DRIVER_BINDING_PROTOCOL *This,
 
1365
  IN EFI_HANDLE                  Controller,
 
1366
  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
 
1367
  )
 
1368
{
 
1369
  EFI_STATUS              Status;
 
1370
  EFI_PCI_IO_PROTOCOL     *PciIo;
 
1371
  USB_CLASSC              UsbClassCReg;
 
1372
 
 
1373
  //
 
1374
  // Test whether there is PCI IO Protocol attached on the controller handle.
 
1375
  //
 
1376
  Status = gBS->OpenProtocol (
 
1377
                  Controller,
 
1378
                  &gEfiPciIoProtocolGuid,
 
1379
                  (VOID **) &PciIo,
 
1380
                  This->DriverBindingHandle,
 
1381
                  Controller,
 
1382
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 
1383
                  );
 
1384
 
 
1385
  if (EFI_ERROR (Status)) {
 
1386
    return EFI_UNSUPPORTED;
 
1387
  }
 
1388
 
 
1389
  Status = PciIo->Pci.Read (
 
1390
                        PciIo,
 
1391
                        EfiPciIoWidthUint8,
 
1392
                        PCI_CLASSCODE_OFFSET,
 
1393
                        sizeof (USB_CLASSC) / sizeof (UINT8),
 
1394
                        &UsbClassCReg
 
1395
                        );
 
1396
 
 
1397
  if (EFI_ERROR (Status)) {
 
1398
    Status = EFI_UNSUPPORTED;
 
1399
    goto ON_EXIT;
 
1400
  }
 
1401
 
 
1402
  //
 
1403
  // Test whether the controller belongs to Ehci type
 
1404
  //
 
1405
  if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB)
 
1406
      || ((UsbClassCReg.ProgInterface != PCI_IF_EHCI) && (UsbClassCReg.ProgInterface !=PCI_IF_UHCI))) {
 
1407
 
 
1408
    Status = EFI_UNSUPPORTED;
 
1409
  }
 
1410
 
 
1411
ON_EXIT:
 
1412
  gBS->CloseProtocol (
 
1413
         Controller,
 
1414
         &gEfiPciIoProtocolGuid,
 
1415
         This->DriverBindingHandle,
 
1416
         Controller
 
1417
         );
 
1418
 
 
1419
  return Status;
 
1420
}
 
1421
 
 
1422
/**
 
1423
  Get the usb debug port related information.
 
1424
 
 
1425
  @param  Ehc                The EHCI device.
 
1426
 
 
1427
  @retval RETURN_SUCCESS     Get debug port number, bar and offset successfully.
 
1428
  @retval Others             The usb host controller does not supported usb debug port capability.
 
1429
 
 
1430
**/
 
1431
EFI_STATUS
 
1432
EhcGetUsbDebugPortInfo (
 
1433
  IN  USB2_HC_DEV     *Ehc
 
1434
 )
 
1435
{
 
1436
  EFI_PCI_IO_PROTOCOL *PciIo;
 
1437
  UINT16              PciStatus;
 
1438
  UINT8               CapabilityPtr;
 
1439
  UINT8               CapabilityId;
 
1440
  UINT16              DebugPort;
 
1441
  EFI_STATUS          Status;
 
1442
 
 
1443
  ASSERT (Ehc->PciIo != NULL);
 
1444
  PciIo = Ehc->PciIo;
 
1445
 
 
1446
  //
 
1447
  // Detect if the EHCI host controller support Capaility Pointer.
 
1448
  //
 
1449
  Status = PciIo->Pci.Read (
 
1450
                        PciIo,
 
1451
                        EfiPciIoWidthUint8,
 
1452
                        PCI_PRIMARY_STATUS_OFFSET,
 
1453
                        sizeof (UINT16),
 
1454
                        &PciStatus
 
1455
                        );
 
1456
 
 
1457
  if (EFI_ERROR (Status)) {
 
1458
    return Status;
 
1459
  }
 
1460
 
 
1461
  if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {
 
1462
    //
 
1463
    // The Pci Device Doesn't Support Capability Pointer.
 
1464
    //
 
1465
    return EFI_UNSUPPORTED;
 
1466
  }
 
1467
 
 
1468
  //
 
1469
  // Get Pointer To Capability List
 
1470
  //
 
1471
  Status = PciIo->Pci.Read (
 
1472
                        PciIo,
 
1473
                        EfiPciIoWidthUint8,
 
1474
                        PCI_CAPBILITY_POINTER_OFFSET,
 
1475
                        1,
 
1476
                        &CapabilityPtr
 
1477
                        );
 
1478
 
 
1479
  if (EFI_ERROR (Status)) {
 
1480
    return Status;
 
1481
  }
 
1482
 
 
1483
  //
 
1484
  // Find Capability ID 0xA, Which Is For Debug Port
 
1485
  //
 
1486
  while (CapabilityPtr != 0) {
 
1487
    Status = PciIo->Pci.Read (
 
1488
                          PciIo,
 
1489
                          EfiPciIoWidthUint8,
 
1490
                          CapabilityPtr,
 
1491
                          1,
 
1492
                          &CapabilityId
 
1493
                          );
 
1494
 
 
1495
    if (EFI_ERROR (Status)) {
 
1496
      return Status;
 
1497
    }
 
1498
 
 
1499
    if (CapabilityId == EHC_DEBUG_PORT_CAP_ID) {
 
1500
      break;
 
1501
    }
 
1502
 
 
1503
    Status = PciIo->Pci.Read (
 
1504
                          PciIo,
 
1505
                          EfiPciIoWidthUint8,
 
1506
                          CapabilityPtr + 1,
 
1507
                          1,
 
1508
                          &CapabilityPtr
 
1509
                          );
 
1510
 
 
1511
    if (EFI_ERROR (Status)) {
 
1512
      return Status;
 
1513
    }
 
1514
  }
 
1515
 
 
1516
  //
 
1517
  // No Debug Port Capability Found
 
1518
  //
 
1519
  if (CapabilityPtr == 0) {
 
1520
    return EFI_UNSUPPORTED;
 
1521
  }
 
1522
 
 
1523
  //
 
1524
  // Get The Base Address Of Debug Port Register In Debug Port Capability Register
 
1525
  //
 
1526
  Status = PciIo->Pci.Read (
 
1527
                        Ehc->PciIo,
 
1528
                        EfiPciIoWidthUint8,
 
1529
                        CapabilityPtr + 2,
 
1530
                        sizeof (UINT16),
 
1531
                        &DebugPort
 
1532
                        );
 
1533
 
 
1534
  if (EFI_ERROR (Status)) {
 
1535
    return Status;
 
1536
  }
 
1537
 
 
1538
  Ehc->DebugPortOffset = DebugPort & 0x1FFF;
 
1539
  Ehc->DebugPortBarNum = (UINT8)((DebugPort >> 13) - 1);
 
1540
  Ehc->DebugPortNum    = (UINT8)((Ehc->HcStructParams & 0x00F00000) >> 20);
 
1541
 
 
1542
  return EFI_SUCCESS;
 
1543
}
 
1544
 
 
1545
 
 
1546
/**
 
1547
  Create and initialize a USB2_HC_DEV.
 
1548
 
 
1549
  @param  PciIo                  The PciIo on this device.
 
1550
  @param  DevicePath             The device path of host controller.
 
1551
  @param  OriginalPciAttributes  Original PCI attributes.
 
1552
 
 
1553
  @return  The allocated and initialized USB2_HC_DEV structure if created,
 
1554
           otherwise NULL.
 
1555
 
 
1556
**/
 
1557
USB2_HC_DEV *
 
1558
EhcCreateUsb2Hc (
 
1559
  IN EFI_PCI_IO_PROTOCOL       *PciIo,
 
1560
  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
 
1561
  IN UINT64                    OriginalPciAttributes
 
1562
  )
 
1563
{
 
1564
  USB2_HC_DEV             *Ehc;
 
1565
  EFI_STATUS              Status;
 
1566
 
 
1567
  Ehc = AllocateZeroPool (sizeof (USB2_HC_DEV));
 
1568
 
 
1569
  if (Ehc == NULL) {
 
1570
    return NULL;
 
1571
  }
 
1572
 
 
1573
  //
 
1574
  // Init EFI_USB2_HC_PROTOCOL interface and private data structure
 
1575
  //
 
1576
  Ehc->Signature                        = USB2_HC_DEV_SIGNATURE;
 
1577
 
 
1578
  Ehc->Usb2Hc.GetCapability             = EhcGetCapability;
 
1579
  Ehc->Usb2Hc.Reset                     = EhcReset;
 
1580
  Ehc->Usb2Hc.GetState                  = EhcGetState;
 
1581
  Ehc->Usb2Hc.SetState                  = EhcSetState;
 
1582
  Ehc->Usb2Hc.ControlTransfer           = EhcControlTransfer;
 
1583
  Ehc->Usb2Hc.BulkTransfer              = EhcBulkTransfer;
 
1584
  Ehc->Usb2Hc.AsyncInterruptTransfer    = EhcAsyncInterruptTransfer;
 
1585
  Ehc->Usb2Hc.SyncInterruptTransfer     = EhcSyncInterruptTransfer;
 
1586
  Ehc->Usb2Hc.IsochronousTransfer       = EhcIsochronousTransfer;
 
1587
  Ehc->Usb2Hc.AsyncIsochronousTransfer  = EhcAsyncIsochronousTransfer;
 
1588
  Ehc->Usb2Hc.GetRootHubPortStatus      = EhcGetRootHubPortStatus;
 
1589
  Ehc->Usb2Hc.SetRootHubPortFeature     = EhcSetRootHubPortFeature;
 
1590
  Ehc->Usb2Hc.ClearRootHubPortFeature   = EhcClearRootHubPortFeature;
 
1591
  Ehc->Usb2Hc.MajorRevision             = 0x2;
 
1592
  Ehc->Usb2Hc.MinorRevision             = 0x0;
 
1593
 
 
1594
  Ehc->PciIo                 = PciIo;
 
1595
  Ehc->DevicePath            = DevicePath;
 
1596
  Ehc->OriginalPciAttributes = OriginalPciAttributes;
 
1597
 
 
1598
  InitializeListHead (&Ehc->AsyncIntTransfers);
 
1599
 
 
1600
  Ehc->HcStructParams = EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET);
 
1601
  Ehc->HcCapParams    = EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET);
 
1602
  Ehc->CapLen         = EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET) & 0x0FF;
 
1603
 
 
1604
  DEBUG ((EFI_D_INFO, "EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen));
 
1605
 
 
1606
  //
 
1607
  // EHCI Controllers with a CapLen of 0 are ignored.
 
1608
  //
 
1609
  if (Ehc->CapLen == 0) {
 
1610
    gBS->FreePool (Ehc);
 
1611
    return NULL;
 
1612
  }
 
1613
  
 
1614
  EhcGetUsbDebugPortInfo (Ehc);
 
1615
 
 
1616
  //
 
1617
  // Create AsyncRequest Polling Timer
 
1618
  //
 
1619
  Status = gBS->CreateEvent (
 
1620
                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
 
1621
                  TPL_CALLBACK,
 
1622
                  EhcMonitorAsyncRequests,
 
1623
                  Ehc,
 
1624
                  &Ehc->PollTimer
 
1625
                  );
 
1626
 
 
1627
  if (EFI_ERROR (Status)) {
 
1628
    gBS->FreePool (Ehc);
 
1629
    return NULL;
 
1630
  }
 
1631
 
 
1632
  return Ehc;
 
1633
}
 
1634
 
 
1635
/**
 
1636
  One notified function to stop the Host Controller when gBS->ExitBootServices() called.
 
1637
 
 
1638
  @param  Event                   Pointer to this event
 
1639
  @param  Context                 Event hanlder private data
 
1640
 
 
1641
**/
 
1642
VOID
 
1643
EFIAPI
 
1644
EhcExitBootService (
 
1645
  EFI_EVENT                      Event,
 
1646
  VOID                           *Context
 
1647
  )
 
1648
 
 
1649
{
 
1650
  USB2_HC_DEV   *Ehc;
 
1651
 
 
1652
  Ehc = (USB2_HC_DEV *) Context;
 
1653
 
 
1654
  //
 
1655
  // Reset the Host Controller
 
1656
  //
 
1657
  EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
 
1658
}
 
1659
 
 
1660
 
 
1661
/**
 
1662
  Starting the Usb EHCI Driver.
 
1663
 
 
1664
  @param  This                 Protocol instance pointer.
 
1665
  @param  Controller           Handle of device to test.
 
1666
  @param  RemainingDevicePath  Not used.
 
1667
 
 
1668
  @return EFI_SUCCESS          supports this device.
 
1669
  @return EFI_UNSUPPORTED      do not support this device.
 
1670
  @return EFI_DEVICE_ERROR     cannot be started due to device Error.
 
1671
  @return EFI_OUT_OF_RESOURCES cannot allocate resources.
 
1672
 
 
1673
**/
 
1674
EFI_STATUS
 
1675
EFIAPI
 
1676
EhcDriverBindingStart (
 
1677
  IN EFI_DRIVER_BINDING_PROTOCOL *This,
 
1678
  IN EFI_HANDLE                  Controller,
 
1679
  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
 
1680
  )
 
1681
{
 
1682
  EFI_STATUS              Status;
 
1683
  USB2_HC_DEV             *Ehc;
 
1684
  EFI_PCI_IO_PROTOCOL     *PciIo;
 
1685
  EFI_PCI_IO_PROTOCOL     *Instance;
 
1686
  UINT64                  Supports;
 
1687
  UINT64                  OriginalPciAttributes;
 
1688
  BOOLEAN                 PciAttributesSaved;
 
1689
  USB_CLASSC              UsbClassCReg;
 
1690
  EFI_HANDLE              *HandleBuffer;
 
1691
  UINTN                   NumberOfHandles;
 
1692
  UINTN                   Index;
 
1693
  UINTN                   UhciSegmentNumber;
 
1694
  UINTN                   UhciBusNumber;
 
1695
  UINTN                   UhciDeviceNumber;
 
1696
  UINTN                   UhciFunctionNumber;
 
1697
  UINTN                   EhciSegmentNumber;
 
1698
  UINTN                   EhciBusNumber;
 
1699
  UINTN                   EhciDeviceNumber;
 
1700
  UINTN                   EhciFunctionNumber;
 
1701
  UINT32                  State;
 
1702
  EFI_DEVICE_PATH_PROTOCOL  *HcDevicePath;
 
1703
 
 
1704
  //
 
1705
  // Open the PciIo Protocol, then enable the USB host controller
 
1706
  //
 
1707
  Status = gBS->OpenProtocol (
 
1708
                  Controller,
 
1709
                  &gEfiPciIoProtocolGuid,
 
1710
                  (VOID **) &PciIo,
 
1711
                  This->DriverBindingHandle,
 
1712
                  Controller,
 
1713
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 
1714
                  );
 
1715
 
 
1716
  if (EFI_ERROR (Status)) {
 
1717
    return Status;
 
1718
  }
 
1719
 
 
1720
  //
 
1721
  // Open Device Path Protocol for on USB host controller
 
1722
  //
 
1723
  HcDevicePath = NULL;
 
1724
  Status = gBS->OpenProtocol (
 
1725
                  Controller,
 
1726
                  &gEfiDevicePathProtocolGuid,
 
1727
                  (VOID **) &HcDevicePath,
 
1728
                  This->DriverBindingHandle,
 
1729
                  Controller,
 
1730
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
 
1731
                  );
 
1732
 
 
1733
  PciAttributesSaved = FALSE;
 
1734
  //
 
1735
  // Save original PCI attributes
 
1736
  //
 
1737
  Status = PciIo->Attributes (
 
1738
                    PciIo,
 
1739
                    EfiPciIoAttributeOperationGet,
 
1740
                    0,
 
1741
                    &OriginalPciAttributes
 
1742
                    );
 
1743
 
 
1744
  if (EFI_ERROR (Status)) {
 
1745
    goto CLOSE_PCIIO;
 
1746
  }
 
1747
  PciAttributesSaved = TRUE;
 
1748
 
 
1749
  Status = PciIo->Attributes (
 
1750
                    PciIo,
 
1751
                    EfiPciIoAttributeOperationSupported,
 
1752
                    0,
 
1753
                    &Supports
 
1754
                    );
 
1755
  if (!EFI_ERROR (Status)) {
 
1756
    Supports &= EFI_PCI_DEVICE_ENABLE;
 
1757
    Status = PciIo->Attributes (
 
1758
                      PciIo,
 
1759
                      EfiPciIoAttributeOperationEnable,
 
1760
                      Supports,
 
1761
                      NULL
 
1762
                      );
 
1763
  }
 
1764
 
 
1765
  if (EFI_ERROR (Status)) {
 
1766
    DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to enable controller\n"));
 
1767
    goto CLOSE_PCIIO;
 
1768
  }
 
1769
 
 
1770
  //
 
1771
  // Get the Pci device class code.
 
1772
  //
 
1773
  Status = PciIo->Pci.Read (
 
1774
                        PciIo,
 
1775
                        EfiPciIoWidthUint8,
 
1776
                        PCI_CLASSCODE_OFFSET,
 
1777
                        sizeof (USB_CLASSC) / sizeof (UINT8),
 
1778
                        &UsbClassCReg
 
1779
                        );
 
1780
 
 
1781
  if (EFI_ERROR (Status)) {
 
1782
    Status = EFI_UNSUPPORTED;
 
1783
    goto CLOSE_PCIIO;
 
1784
  }
 
1785
  //
 
1786
  // determine if the device is UHCI host controller or not. If yes, then find out the 
 
1787
  // companion usb ehci host controller and force EHCI driver get attached to it before
 
1788
  // UHCI driver attaches to UHCI host controller.
 
1789
  //
 
1790
  if ((UsbClassCReg.ProgInterface == PCI_IF_UHCI) &&
 
1791
       (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) && 
 
1792
       (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
 
1793
    Status = PciIo->GetLocation (
 
1794
                    PciIo,
 
1795
                    &UhciSegmentNumber,
 
1796
                    &UhciBusNumber,
 
1797
                    &UhciDeviceNumber,
 
1798
                    &UhciFunctionNumber
 
1799
                    );
 
1800
    if (EFI_ERROR (Status)) {
 
1801
      goto CLOSE_PCIIO;
 
1802
    }
 
1803
 
 
1804
    Status = gBS->LocateHandleBuffer (
 
1805
                    ByProtocol,
 
1806
                    &gEfiPciIoProtocolGuid,
 
1807
                    NULL,
 
1808
                    &NumberOfHandles,
 
1809
                    &HandleBuffer
 
1810
                    );
 
1811
    if (EFI_ERROR (Status)) {
 
1812
      goto CLOSE_PCIIO;
 
1813
    }
 
1814
 
 
1815
    for (Index = 0; Index < NumberOfHandles; Index++) {
 
1816
      //
 
1817
      // Get the device path on this handle
 
1818
      //
 
1819
      Status = gBS->HandleProtocol (
 
1820
                    HandleBuffer[Index],
 
1821
                    &gEfiPciIoProtocolGuid,
 
1822
                    (VOID **)&Instance
 
1823
                    );
 
1824
      ASSERT_EFI_ERROR (Status);
 
1825
 
 
1826
      Status = Instance->Pci.Read (
 
1827
                    Instance,
 
1828
                    EfiPciIoWidthUint8,
 
1829
                    PCI_CLASSCODE_OFFSET,
 
1830
                    sizeof (USB_CLASSC) / sizeof (UINT8),
 
1831
                    &UsbClassCReg
 
1832
                    );
 
1833
 
 
1834
      if (EFI_ERROR (Status)) {
 
1835
        Status = EFI_UNSUPPORTED;
 
1836
        goto CLOSE_PCIIO;
 
1837
      }
 
1838
 
 
1839
      if ((UsbClassCReg.ProgInterface == PCI_IF_EHCI) &&
 
1840
           (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) && 
 
1841
           (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
 
1842
        Status = Instance->GetLocation (
 
1843
                    Instance,
 
1844
                    &EhciSegmentNumber,
 
1845
                    &EhciBusNumber,
 
1846
                    &EhciDeviceNumber,
 
1847
                    &EhciFunctionNumber
 
1848
                    );
 
1849
        if (EFI_ERROR (Status)) {
 
1850
          goto CLOSE_PCIIO;
 
1851
        }
 
1852
        //
 
1853
        // Currently, the judgment on the companion usb host controller is through the
 
1854
        // same bus number, which may vary on different platform.
 
1855
        //
 
1856
        if (EhciBusNumber == UhciBusNumber) {
 
1857
          gBS->CloseProtocol (
 
1858
                    Controller,
 
1859
                    &gEfiPciIoProtocolGuid,
 
1860
                    This->DriverBindingHandle,
 
1861
                    Controller
 
1862
                    );
 
1863
          EhcDriverBindingStart(This, HandleBuffer[Index], NULL);
 
1864
        }
 
1865
      }
 
1866
    }
 
1867
    Status = EFI_NOT_FOUND;
 
1868
    goto CLOSE_PCIIO;
 
1869
  }
 
1870
 
 
1871
  //
 
1872
  // Create then install USB2_HC_PROTOCOL
 
1873
  //
 
1874
  Ehc = EhcCreateUsb2Hc (PciIo, HcDevicePath, OriginalPciAttributes);
 
1875
 
 
1876
  if (Ehc == NULL) {
 
1877
    DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to create USB2_HC\n"));
 
1878
 
 
1879
    Status = EFI_OUT_OF_RESOURCES;
 
1880
    goto CLOSE_PCIIO;
 
1881
  }
 
1882
 
 
1883
  Status = gBS->InstallProtocolInterface (
 
1884
                  &Controller,
 
1885
                  &gEfiUsb2HcProtocolGuid,
 
1886
                  EFI_NATIVE_INTERFACE,
 
1887
                  &Ehc->Usb2Hc
 
1888
                  );
 
1889
 
 
1890
  if (EFI_ERROR (Status)) {
 
1891
    DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
 
1892
    goto FREE_POOL;
 
1893
  }
 
1894
 
 
1895
  //
 
1896
  // Robustnesss improvement such as for Duet platform
 
1897
  // Default is not required.
 
1898
  //
 
1899
  if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
 
1900
    EhcClearLegacySupport (Ehc);
 
1901
  }
 
1902
 
 
1903
  if (Ehc->DebugPortNum != 0) {
 
1904
    State = EhcReadDbgRegister(Ehc, 0);
 
1905
    if ((State & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) != (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) {
 
1906
      EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
 
1907
    }
 
1908
  }
 
1909
 
 
1910
  Status = EhcInitHC (Ehc);
 
1911
 
 
1912
  if (EFI_ERROR (Status)) {
 
1913
    DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to init host controller\n"));
 
1914
    goto UNINSTALL_USBHC;
 
1915
  }
 
1916
 
 
1917
  //
 
1918
  // Start the asynchronous interrupt monitor
 
1919
  //
 
1920
  Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL);
 
1921
 
 
1922
  if (EFI_ERROR (Status)) {
 
1923
    DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
 
1924
 
 
1925
    EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
 
1926
    goto UNINSTALL_USBHC;
 
1927
  }
 
1928
 
 
1929
  //
 
1930
  // Create event to stop the HC when exit boot service.
 
1931
  //
 
1932
  Status = gBS->CreateEventEx (
 
1933
                  EVT_NOTIFY_SIGNAL,
 
1934
                  TPL_NOTIFY,
 
1935
                  EhcExitBootService,
 
1936
                  Ehc,
 
1937
                  &gEfiEventExitBootServicesGuid,
 
1938
                  &Ehc->ExitBootServiceEvent
 
1939
                  );
 
1940
  if (EFI_ERROR (Status)) {
 
1941
    goto UNINSTALL_USBHC;
 
1942
  }
 
1943
 
 
1944
  //
 
1945
  // Install the component name protocol, don't fail the start
 
1946
  // because of something for display.
 
1947
  //
 
1948
  AddUnicodeString2 (
 
1949
    "eng",
 
1950
    gEhciComponentName.SupportedLanguages,
 
1951
    &Ehc->ControllerNameTable,
 
1952
    L"Enhanced Host Controller (USB 2.0)",
 
1953
    TRUE
 
1954
    );
 
1955
  AddUnicodeString2 (
 
1956
    "en",
 
1957
    gEhciComponentName2.SupportedLanguages,
 
1958
    &Ehc->ControllerNameTable,
 
1959
    L"Enhanced Host Controller (USB 2.0)",
 
1960
    FALSE
 
1961
    );
 
1962
 
 
1963
 
 
1964
  DEBUG ((EFI_D_INFO, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller));
 
1965
  return EFI_SUCCESS;
 
1966
 
 
1967
UNINSTALL_USBHC:
 
1968
  gBS->UninstallProtocolInterface (
 
1969
         Controller,
 
1970
         &gEfiUsb2HcProtocolGuid,
 
1971
         &Ehc->Usb2Hc
 
1972
         );
 
1973
 
 
1974
FREE_POOL:
 
1975
  EhcFreeSched (Ehc);
 
1976
  gBS->CloseEvent (Ehc->PollTimer);
 
1977
  gBS->FreePool (Ehc);
 
1978
 
 
1979
CLOSE_PCIIO:
 
1980
  if (PciAttributesSaved) {
 
1981
    //
 
1982
    // Restore original PCI attributes
 
1983
    //
 
1984
    PciIo->Attributes (
 
1985
                    PciIo,
 
1986
                    EfiPciIoAttributeOperationSet,
 
1987
                    OriginalPciAttributes,
 
1988
                    NULL
 
1989
                    );
 
1990
  }
 
1991
 
 
1992
  gBS->CloseProtocol (
 
1993
         Controller,
 
1994
         &gEfiPciIoProtocolGuid,
 
1995
         This->DriverBindingHandle,
 
1996
         Controller
 
1997
         );
 
1998
 
 
1999
  return Status;
 
2000
}
 
2001
 
 
2002
 
 
2003
/**
 
2004
  Stop this driver on ControllerHandle. Support stoping any child handles
 
2005
  created by this driver.
 
2006
 
 
2007
  @param  This                 Protocol instance pointer.
 
2008
  @param  Controller           Handle of device to stop driver on.
 
2009
  @param  NumberOfChildren     Number of Children in the ChildHandleBuffer.
 
2010
  @param  ChildHandleBuffer    List of handles for the children we need to stop.
 
2011
 
 
2012
  @return EFI_SUCCESS          Success.
 
2013
  @return EFI_DEVICE_ERROR     Fail.
 
2014
 
 
2015
**/
 
2016
EFI_STATUS
 
2017
EFIAPI
 
2018
EhcDriverBindingStop (
 
2019
  IN EFI_DRIVER_BINDING_PROTOCOL *This,
 
2020
  IN EFI_HANDLE                  Controller,
 
2021
  IN UINTN                       NumberOfChildren,
 
2022
  IN EFI_HANDLE                  *ChildHandleBuffer
 
2023
  )
 
2024
{
 
2025
  EFI_STATUS            Status;
 
2026
  EFI_USB2_HC_PROTOCOL  *Usb2Hc;
 
2027
  EFI_PCI_IO_PROTOCOL   *PciIo;
 
2028
  USB2_HC_DEV           *Ehc;
 
2029
 
 
2030
  //
 
2031
  // Test whether the Controller handler passed in is a valid
 
2032
  // Usb controller handle that should be supported, if not,
 
2033
  // return the error status directly
 
2034
  //
 
2035
  Status = gBS->OpenProtocol (
 
2036
                  Controller,
 
2037
                  &gEfiUsb2HcProtocolGuid,
 
2038
                  (VOID **) &Usb2Hc,
 
2039
                  This->DriverBindingHandle,
 
2040
                  Controller,
 
2041
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
 
2042
                  );
 
2043
 
 
2044
  if (EFI_ERROR (Status)) {
 
2045
    return Status;
 
2046
  }
 
2047
 
 
2048
  Ehc   = EHC_FROM_THIS (Usb2Hc);
 
2049
  PciIo = Ehc->PciIo;
 
2050
 
 
2051
  //
 
2052
  // Stop AsyncRequest Polling timer then stop the EHCI driver
 
2053
  // and uninstall the EHCI protocl.
 
2054
  //
 
2055
  gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL);
 
2056
  EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
 
2057
 
 
2058
  Status = gBS->UninstallProtocolInterface (
 
2059
                  Controller,
 
2060
                  &gEfiUsb2HcProtocolGuid,
 
2061
                  Usb2Hc
 
2062
                  );
 
2063
 
 
2064
  if (EFI_ERROR (Status)) {
 
2065
    return Status;
 
2066
  }
 
2067
 
 
2068
  if (Ehc->PollTimer != NULL) {
 
2069
    gBS->CloseEvent (Ehc->PollTimer);
 
2070
  }
 
2071
 
 
2072
  if (Ehc->ExitBootServiceEvent != NULL) {
 
2073
    gBS->CloseEvent (Ehc->ExitBootServiceEvent);
 
2074
  }
 
2075
 
 
2076
  EhcFreeSched (Ehc);
 
2077
 
 
2078
  if (Ehc->ControllerNameTable != NULL) {
 
2079
    FreeUnicodeStringTable (Ehc->ControllerNameTable);
 
2080
  }
 
2081
 
 
2082
  //
 
2083
  // Disable routing of all ports to EHCI controller, so all ports are 
 
2084
  // routed back to the UHCI controller.
 
2085
  //
 
2086
  EhcClearOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
 
2087
 
 
2088
  //
 
2089
  // Restore original PCI attributes
 
2090
  //
 
2091
  PciIo->Attributes (
 
2092
                  PciIo,
 
2093
                  EfiPciIoAttributeOperationSet,
 
2094
                  Ehc->OriginalPciAttributes,
 
2095
                  NULL
 
2096
                  );
 
2097
 
 
2098
  gBS->CloseProtocol (
 
2099
         Controller,
 
2100
         &gEfiPciIoProtocolGuid,
 
2101
         This->DriverBindingHandle,
 
2102
         Controller
 
2103
         );
 
2104
 
 
2105
  FreePool (Ehc);
 
2106
 
 
2107
  return EFI_SUCCESS;
 
2108
}
 
2109