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