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