Some library instance's PCD is missing in FPD file for a module, it break single...
[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
367 0x10,\r
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
488 \r
489 HcDev = NULL;\r
490\r
491 Status = gBS->OpenProtocol (\r
492 Controller,\r
493 &gEfiPciIoProtocolGuid,\r
494 (VOID **) &PciIo,\r
495 This->DriverBindingHandle,\r
496 Controller,\r
497 EFI_OPEN_PROTOCOL_BY_DRIVER\r
498 );\r
499 if (EFI_ERROR (Status)) {\r
500 return Status;\r
501 }\r
562d2849 502\r
878ddf1f 503 //\r
504 // Turn off USB emulation\r
505 //\r
506 TurnOffUSBEmulation (PciIo);\r
507\r
508 //\r
509 // Enable the USB Host Controller\r
510 //\r
511 Status = PciIo->Attributes (\r
512 PciIo,\r
513 EfiPciIoAttributeOperationEnable,\r
514 EFI_PCI_DEVICE_ENABLE,\r
515 NULL\r
516 );\r
517 if (EFI_ERROR (Status)) {\r
518 gBS->CloseProtocol (\r
562d2849 519 Controller,\r
520 &gEfiPciIoProtocolGuid,\r
521 This->DriverBindingHandle,\r
522 Controller\r
523 );\r
878ddf1f 524 return EFI_UNSUPPORTED;\r
525 }\r
526\r
527 //\r
528 // allocate memory for UHC private data structure\r
529 //\r
530 HcDev = AllocateZeroPool (sizeof (USB_HC_DEV));\r
531 if (HcDev == NULL) {\r
532 gBS->CloseProtocol (\r
562d2849 533 Controller,\r
534 &gEfiPciIoProtocolGuid,\r
535 This->DriverBindingHandle,\r
536 Controller\r
537 );\r
878ddf1f 538 return EFI_OUT_OF_RESOURCES;\r
539 }\r
562d2849 540\r
878ddf1f 541 //\r
542 // init EFI_USB_HC_PROTOCOL protocol interface and install the protocol\r
543 //\r
544 HcDev->UsbHc.Reset = UHCIReset;\r
545 HcDev->UsbHc.GetState = UHCIGetState;\r
546 HcDev->UsbHc.SetState = UHCISetState;\r
547 HcDev->UsbHc.ControlTransfer = UHCIControlTransfer;\r
548 HcDev->UsbHc.BulkTransfer = UHCIBulkTransfer;\r
549 HcDev->UsbHc.AsyncInterruptTransfer = UHCIAsyncInterruptTransfer;\r
550 HcDev->UsbHc.SyncInterruptTransfer = UHCISyncInterruptTransfer;\r
551 HcDev->UsbHc.IsochronousTransfer = UHCIIsochronousTransfer;\r
552 HcDev->UsbHc.AsyncIsochronousTransfer = UHCIAsyncIsochronousTransfer;\r
553 HcDev->UsbHc.GetRootHubPortNumber = UHCIGetRootHubPortNumber;\r
554 HcDev->UsbHc.GetRootHubPortStatus = UHCIGetRootHubPortStatus;\r
555 HcDev->UsbHc.SetRootHubPortFeature = UHCISetRootHubPortFeature;\r
556 HcDev->UsbHc.ClearRootHubPortFeature = UHCIClearRootHubPortFeature;\r
557\r
558 HcDev->UsbHc.MajorRevision = 0x1;\r
559 HcDev->UsbHc.MinorRevision = 0x1;\r
560\r
562d2849 561 //\r
562 //\r
563 // init EFI_USB2_HC_PROTOCOL protocol interface and install the protocol\r
564 //\r
565 HcDev->Usb2Hc.GetCapability = UHCI2GetCapability;\r
566 HcDev->Usb2Hc.Reset = UHCI2Reset;\r
567 HcDev->Usb2Hc.GetState = UHCI2GetState;\r
568 HcDev->Usb2Hc.SetState = UHCI2SetState;\r
569 HcDev->Usb2Hc.ControlTransfer = UHCI2ControlTransfer;\r
570 HcDev->Usb2Hc.BulkTransfer = UHCI2BulkTransfer;\r
571 HcDev->Usb2Hc.AsyncInterruptTransfer = UHCI2AsyncInterruptTransfer;\r
572 HcDev->Usb2Hc.SyncInterruptTransfer = UHCI2SyncInterruptTransfer;\r
573 HcDev->Usb2Hc.IsochronousTransfer = UHCI2IsochronousTransfer;\r
574 HcDev->Usb2Hc.AsyncIsochronousTransfer = UHCI2AsyncIsochronousTransfer;\r
575 HcDev->Usb2Hc.GetRootHubPortStatus = UHCI2GetRootHubPortStatus;\r
576 HcDev->Usb2Hc.SetRootHubPortFeature = UHCI2SetRootHubPortFeature;\r
577 HcDev->Usb2Hc.ClearRootHubPortFeature = UHCI2ClearRootHubPortFeature;\r
578 \r
579 HcDev->Usb2Hc.MajorRevision = 0x1;\r
580 HcDev->Usb2Hc.MinorRevision = 0x1;\r
581 \r
878ddf1f 582 //\r
583 // Init UHCI private data structures\r
584 //\r
585 HcDev->Signature = USB_HC_DEV_SIGNATURE;\r
586 HcDev->PciIo = PciIo;\r
587\r
588 FlBaseAddrReg = USBFLBASEADD;\r
589\r
590 //\r
591 // Allocate and Init Host Controller's Frame List Entry\r
592 //\r
593 Status = CreateFrameList (HcDev, (UINT32) FlBaseAddrReg);\r
594 if (EFI_ERROR (Status)) {\r
595\r
596 if (HcDev != NULL) {\r
597 gBS->FreePool (HcDev);\r
598 }\r
599\r
600 gBS->CloseProtocol (\r
562d2849 601 Controller,\r
602 &gEfiPciIoProtocolGuid,\r
603 This->DriverBindingHandle,\r
604 Controller\r
605 );\r
878ddf1f 606 return EFI_OUT_OF_RESOURCES;\r
607 }\r
562d2849 608\r
878ddf1f 609 //\r
610 // Init interrupt list head in the HcDev structure.\r
611 //\r
612 InitializeListHead (&(HcDev->InterruptListHead));\r
613\r
614 //\r
615 // Create timer for interrupt transfer result polling\r
616 //\r
617 Status = gBS->CreateEvent (\r
618 EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,\r
619 EFI_TPL_NOTIFY,\r
620 MonitorInterruptTrans,\r
621 HcDev,\r
622 &HcDev->InterruptTransTimer\r
623 );\r
624 if (EFI_ERROR (Status)) {\r
625\r
626 FreeFrameListEntry (HcDev);\r
627\r
628 if (HcDev != NULL) {\r
629 gBS->FreePool (HcDev);\r
630 }\r
631\r
632 gBS->CloseProtocol (\r
562d2849 633 Controller,\r
634 &gEfiPciIoProtocolGuid,\r
635 This->DriverBindingHandle,\r
636 Controller\r
637 );\r
878ddf1f 638 return EFI_UNSUPPORTED;\r
639 }\r
640\r
641 //\r
642 // Here set interrupt transfer polling timer in 50ms unit.\r
643 //\r
644 Status = gBS->SetTimer (\r
645 HcDev->InterruptTransTimer,\r
646 TimerPeriodic,\r
647 INTERRUPT_POLLING_TIME\r
648 );\r
649 if (EFI_ERROR (Status)) {\r
650 gBS->CloseEvent (HcDev->InterruptTransTimer);\r
651\r
652 FreeFrameListEntry (HcDev);\r
653\r
654 if (HcDev != NULL) {\r
655 gBS->FreePool (HcDev);\r
656 }\r
657\r
658 gBS->CloseProtocol (\r
562d2849 659 Controller,\r
660 &gEfiPciIoProtocolGuid,\r
661 This->DriverBindingHandle,\r
662 Controller\r
663 );\r
878ddf1f 664 return EFI_UNSUPPORTED;\r
665 }\r
666 \r
667 //\r
668 // QH,TD structures must in common buffer that will be\r
669 // accessed by both cpu and usb bus master at the same time.\r
670 // so, there must has memory management for QH,TD structures.\r
671 //\r
672 Status = InitializeMemoryManagement (HcDev);\r
673 if (EFI_ERROR (Status)) {\r
674 \r
675 gBS->CloseEvent (HcDev->InterruptTransTimer);\r
676 \r
677 FreeFrameListEntry (HcDev);\r
678\r
679 if (HcDev != NULL) {\r
680 gBS->FreePool (HcDev);\r
681 }\r
682\r
683 gBS->CloseProtocol (\r
684 Controller, \r
685 &gEfiPciIoProtocolGuid, \r
686 This->DriverBindingHandle, \r
687 Controller\r
688 );\r
689 return Status;\r
690 }\r
562d2849 691\r
878ddf1f 692 //\r
693 // Install Host Controller Protocol\r
694 //\r
695 Status = gBS->InstallProtocolInterface (\r
696 &Controller,\r
697 &gEfiUsbHcProtocolGuid,\r
698 EFI_NATIVE_INTERFACE,\r
699 &HcDev->UsbHc\r
700 );\r
701 if (EFI_ERROR (Status)) {\r
702 gBS->CloseEvent (HcDev->InterruptTransTimer);\r
703 FreeFrameListEntry (HcDev);\r
704 DelMemoryManagement (HcDev);\r
705\r
706 if (HcDev != NULL) {\r
707 gBS->FreePool (HcDev);\r
708 }\r
709\r
710 gBS->CloseProtocol (\r
562d2849 711 Controller,\r
712 &gEfiPciIoProtocolGuid,\r
713 This->DriverBindingHandle,\r
714 Controller\r
715 );\r
716 return Status;\r
717 }\r
718\r
719 //\r
720 // Install USB2.0 Host Controller Protocol\r
721 //\r
722 Status = gBS->InstallProtocolInterface (\r
723 &Controller,\r
724 &gEfiUsb2HcProtocolGuid,\r
725 EFI_NATIVE_INTERFACE,\r
726 &HcDev->Usb2Hc\r
727 );\r
728 if (EFI_ERROR (Status)) {\r
729 gBS->CloseEvent (HcDev->InterruptTransTimer);\r
730 FreeFrameListEntry (HcDev);\r
731 DelMemoryManagement (HcDev);\r
732\r
733 if (HcDev != NULL) {\r
734 gBS->FreePool (HcDev);\r
735 }\r
736\r
737 gBS->CloseProtocol (\r
738 Controller,\r
739 &gEfiPciIoProtocolGuid,\r
740 This->DriverBindingHandle,\r
741 Controller\r
742 );\r
743\r
878ddf1f 744 return Status;\r
745 }\r
746 \r
747 //\r
748 // component name protocol.\r
749 //\r
562d2849 750\r
878ddf1f 751 HcDev->ControllerNameTable = NULL;\r
752 AddUnicodeString (\r
753 "eng",\r
754 gUhciComponentName.SupportedLanguages,\r
755 &HcDev->ControllerNameTable,\r
756 (CHAR16 *) L"Usb Universal Host Controller"\r
757 );\r
758\r
759 return EFI_SUCCESS;\r
760}\r
761\r
762\r
763EFI_STATUS\r
764UnInstallUHCInterface (\r
765 IN EFI_HANDLE Controller,\r
766 IN EFI_USB_HC_PROTOCOL *This\r
767 )\r
768/*++\r
769 Routine Description:\r
770 UnInstall UHCInterface\r
771 Arguments:\r
772 Controller - Controller handle\r
773 This - Protocol instance pointer.\r
774 Returns:\r
775 EFI_SUCCESS\r
776 others\r
777--*/\r
778{\r
779 USB_HC_DEV *HcDev;\r
780\r
781 HcDev = USB_HC_DEV_FROM_THIS (This);\r
782\r
783 gBS->UninstallProtocolInterface (\r
562d2849 784 Controller,\r
785 &gEfiUsbHcProtocolGuid,\r
786 &HcDev->UsbHc\r
787 );\r
788 \r
789 gBS->UninstallProtocolInterface (\r
790 Controller,\r
791 &gEfiUsb2HcProtocolGuid,\r
792 &HcDev->Usb2Hc\r
793 );\r
794 // \r
878ddf1f 795 // first stop USB Host Controller\r
796 //\r
797 This->SetState (This, EfiUsbHcStateHalt);\r
798\r
799 //\r
800 // Delete interrupt transfer polling timer\r
801 //\r
802 gBS->CloseEvent (HcDev->InterruptTransTimer);\r
803\r
804 //\r
805 // Delete all the asynchronous interrupt transfers in the interrupt list\r
806 // and free associated memory\r
807 //\r
808 ReleaseInterruptList (HcDev, &(HcDev->InterruptListHead));\r
809\r
810 //\r
811 // free Frame List Entry.\r
812 //\r
813 FreeFrameListEntry (HcDev);\r
814\r
815 //\r
816 // Free common buffer allocated for QH,TD structures\r
817 //\r
818 DelMemoryManagement (HcDev);\r
819\r
820 if (HcDev->ControllerNameTable) {\r
821 FreeUnicodeStringTable (HcDev->ControllerNameTable);\r
822 }\r
823 //\r
824 // Disable the USB Host Controller\r
825 //\r
826 HcDev->PciIo->Attributes (\r
827 HcDev->PciIo,\r
828 EfiPciIoAttributeOperationDisable,\r
829 EFI_PCI_DEVICE_ENABLE,\r
830 NULL\r
831 );\r
832\r
833 gBS->FreePool (HcDev);\r
834\r
835 return EFI_SUCCESS;\r
836}\r
837\r
838\r
839EFI_STATUS\r
840EFIAPI\r
841UHCIDriverBindingStop (\r
842 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
843 IN EFI_HANDLE Controller,\r
844 IN UINTN NumberOfChildren,\r
845 IN EFI_HANDLE *ChildHandleBuffer\r
846 )\r
847/*++\r
848\r
849 Routine Description:\r
850 Stop this driver on ControllerHandle. Support stoping any child handles\r
851 created by this driver.\r
852\r
853 Arguments:\r
854 This - Protocol instance pointer.\r
855 Controller - Handle of device to stop driver on\r
856 NumberOfChildren - Number of Children in the ChildHandleBuffer\r
857 ChildHandleBuffer - List of handles for the children we need to stop.\r
858\r
859 Returns:\r
860 EFI_SUCCESS\r
861 others\r
862\r
863--*/\r
864{\r
865 EFI_USB_HC_PROTOCOL *UsbHc;\r
562d2849 866 EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
878ddf1f 867 EFI_STATUS OpenStatus;\r
868\r
869 OpenStatus = gBS->OpenProtocol (\r
870 Controller,\r
871 &gEfiUsbHcProtocolGuid,\r
562d2849 872 (VOID **)&UsbHc,\r
873 This->DriverBindingHandle,\r
874 Controller,\r
875 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
876 );\r
877\r
878 //\r
879 // Test whether the Controller handler passed in is a valid\r
880 // Usb controller handle that should be supported, if not,\r
881 // return the error status directly\r
882 //\r
883 if (EFI_ERROR (OpenStatus)) {\r
884 return OpenStatus;\r
885 }\r
886\r
887 OpenStatus = gBS->OpenProtocol (\r
888 Controller,\r
889 &gEfiUsb2HcProtocolGuid,\r
890 (VOID **) &Usb2Hc,\r
878ddf1f 891 This->DriverBindingHandle,\r
892 Controller,\r
893 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
894 );\r
895\r
896 //\r
897 // Test whether the Controller handler passed in is a valid\r
898 // Usb controller handle that should be supported, if not,\r
899 // return the error status directly\r
900 //\r
901 if (EFI_ERROR (OpenStatus)) {\r
902 return OpenStatus;\r
903 }\r
904 //\r
905 // free all the controller related memory and uninstall UHCI Protocol.\r
906 //\r
907 UnInstallUHCInterface (Controller, UsbHc);\r
908\r
909 gBS->CloseProtocol (\r
562d2849 910 Controller,\r
911 &gEfiPciIoProtocolGuid,\r
912 This->DriverBindingHandle,\r
913 Controller\r
914 );\r
878ddf1f 915\r
916 return EFI_SUCCESS;\r
917\r
918}\r
919\r
920\r
921EFI_STATUS\r
922EFIAPI\r
923UHCIReset (\r
924 IN EFI_USB_HC_PROTOCOL *This,\r
925 IN UINT16 Attributes\r
926 )\r
927/*++\r
928 \r
929 Routine Description:\r
930 Provides software reset for the USB host controller.\r
931 \r
932 Arguments:\r
933 \r
934 This A pointer to the EFI_USB_HC_PROTOCOL instance. \r
935 \r
936 Attributes A bit mask of the reset operation to perform. \r
937 See below for a list of the supported bit mask values.\r
938 \r
939 #define EFI_USB_HC_RESET_GLOBAL 0x0001\r
940 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002\r
941\r
942 EFI_USB_HC_RESET_GLOBAL \r
943 If this bit is set, a global reset signal will be sent to the USB bus.\r
944 This resets all of the USB bus logic, including the USB host \r
945 controller hardware and all the devices attached on the USB bus.\r
946 EFI_USB_HC_RESET_HOST_CONTROLLER \r
947 If this bit is set, the USB host controller hardware will be reset. \r
948 No reset signal will be sent to the USB bus.\r
949 \r
950 Returns:\r
951 EFI_SUCCESS \r
952 The reset operation succeeded.\r
953 EFI_INVALID_PARAMETER \r
954 Attributes is not valid.\r
955 EFI_DEVICE_ERROR \r
956 An error was encountered while attempting to perform \r
957 the reset operation.\r
958--*/\r
959{\r
960 BOOLEAN Match;\r
961 USB_HC_DEV *HcDev;\r
962 UINT32 CommandRegAddr;\r
963 UINT32 FlBaseAddrReg;\r
964 UINT16 Command;\r
965 EFI_STATUS Status;\r
966\r
967 Match = FALSE;\r
968 HcDev = USB_HC_DEV_FROM_THIS (This);\r
969\r
970 CommandRegAddr = (UINT32) (USBCMD);\r
971 FlBaseAddrReg = (UINT32) (USBFLBASEADD);\r
972\r
973 if ((Attributes & EFI_USB_HC_RESET_GLOBAL) != 0) {\r
974 Match = TRUE;\r
975 //\r
976 // set the Global Reset bit in the command register\r
977 //\r
978 Status = ReadUHCCommandReg (\r
562d2849 979 HcDev->PciIo,\r
980 CommandRegAddr,\r
981 &Command\r
982 );\r
878ddf1f 983 if (EFI_ERROR (Status)) {\r
984 return EFI_DEVICE_ERROR;\r
985 }\r
986\r
987 Command |= USBCMD_GRESET;\r
988 Status = WriteUHCCommandReg (\r
562d2849 989 HcDev->PciIo,\r
990 CommandRegAddr,\r
991 Command\r
992 );\r
878ddf1f 993 if (EFI_ERROR (Status)) {\r
994 return EFI_DEVICE_ERROR;\r
995 }\r
996\r
997 //\r
998 // Wait 50ms for root port to let reset complete\r
999 // See UHCI spec page122 Reset signaling\r
1000 //\r
1001 gBS->Stall (ROOT_PORT_REST_TIME);\r
1002\r
1003 //\r
1004 // Clear the Global Reset bit to zero.\r
1005 //\r
1006 Command &= ~USBCMD_GRESET;\r
1007 Status = WriteUHCCommandReg (\r
562d2849 1008 HcDev->PciIo,\r
1009 CommandRegAddr,\r
1010 Command\r
1011 );\r
878ddf1f 1012 if (EFI_ERROR (Status)) {\r
1013 return EFI_DEVICE_ERROR;\r
1014 }\r
1015 //\r
1016 // UHCI spec page120 reset recovery time\r
1017 //\r
1018 gBS->Stall (PORT_RESET_RECOVERY_TIME);\r
1019 }\r
1020\r
1021 if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) {\r
1022 Match = TRUE;\r
1023 //\r
1024 // set Host Controller Reset bit to 1\r
1025 //\r
1026 Status = ReadUHCCommandReg (\r
562d2849 1027 HcDev->PciIo,\r
1028 CommandRegAddr,\r
1029 &Command\r
1030 );\r
878ddf1f 1031 if (EFI_ERROR (Status)) {\r
1032 return EFI_DEVICE_ERROR;\r
1033 }\r
1034\r
1035 Command |= USBCMD_HCRESET;\r
1036 Status = WriteUHCCommandReg (\r
562d2849 1037 HcDev->PciIo,\r
1038 CommandRegAddr,\r
1039 Command\r
1040 );\r
878ddf1f 1041 if (EFI_ERROR (Status)) {\r
1042 return EFI_DEVICE_ERROR;\r
1043 }\r
1044 //\r
1045 // this bit will be reset by Host Controller when reset is completed.\r
1046 // wait 10ms to let reset complete\r
1047 //\r
1048 gBS->Stall (PORT_RESET_RECOVERY_TIME);\r
1049 }\r
1050\r
1051 if (!Match) {\r
1052 return EFI_INVALID_PARAMETER;\r
1053 }\r
1054 \r
1055 //\r
1056 // Delete all old transactions on the USB bus\r
1057 //\r
1058 CleanUsbTransactions (HcDev);\r
1059\r
1060 //\r
1061 // Initialize Universal Host Controller's Frame List Data Structure\r
1062 //\r
1063 InitFrameList (HcDev);\r
1064\r
1065 //\r
1066 // Reset may cause Frame List Base Address Register reset to zero,\r
1067 // so set the original value back again.\r
1068 //\r
1069 SetFrameListBaseAddress (\r
1070 HcDev->PciIo,\r
1071 FlBaseAddrReg,\r
1072 (UINT32) ((UINTN) HcDev->FrameListEntry)\r
1073 );\r
1074\r
1075 return EFI_SUCCESS;\r
1076}\r
1077\r
1078EFI_STATUS\r
1079EFIAPI\r
1080UHCIGetState (\r
1081 IN EFI_USB_HC_PROTOCOL *This,\r
1082 OUT EFI_USB_HC_STATE *State\r
1083 )\r
1084/*++\r
1085 \r
1086 Routine Description:\r
1087 Retrieves current state of the USB host controller.\r
1088 \r
1089 Arguments:\r
1090 \r
1091 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1092 \r
1093 State A pointer to the EFI_USB_HC_STATE data structure that \r
1094 indicates current state of the USB host controller. \r
1095 Type EFI_USB_HC_STATE is defined below.\r
1096 \r
1097 typedef enum {\r
1098 EfiUsbHcStateHalt,\r
1099 EfiUsbHcStateOperational,\r
1100 EfiUsbHcStateSuspend,\r
1101 EfiUsbHcStateMaximum\r
1102 } EFI_USB_HC_STATE;\r
1103 \r
1104 Returns:\r
1105 EFI_SUCCESS \r
1106 The state information of the host controller was returned in State.\r
1107 EFI_INVALID_PARAMETER \r
1108 State is NULL.\r
1109 EFI_DEVICE_ERROR \r
1110 An error was encountered while attempting to retrieve the \r
1111 host controller's current state. \r
1112--*/\r
1113{\r
1114 USB_HC_DEV *HcDev;\r
1115 UINT32 CommandRegAddr;\r
1116 UINT32 StatusRegAddr;\r
1117 UINT16 UhcCommand;\r
1118 UINT16 UhcStatus;\r
1119 EFI_STATUS Status;\r
1120\r
1121 if (State == NULL) {\r
1122 return EFI_INVALID_PARAMETER;\r
1123 }\r
1124\r
1125 HcDev = USB_HC_DEV_FROM_THIS (This);\r
1126\r
1127 CommandRegAddr = (UINT32) (USBCMD);\r
1128 StatusRegAddr = (UINT32) (USBSTS);\r
1129\r
1130 Status = ReadUHCCommandReg (\r
562d2849 1131 HcDev->PciIo,\r
1132 CommandRegAddr,\r
1133 &UhcCommand\r
1134 );\r
878ddf1f 1135\r
1136 if (EFI_ERROR (Status)) {\r
1137 return EFI_DEVICE_ERROR;\r
1138 }\r
1139\r
1140 Status = ReadUHCCommandReg (\r
562d2849 1141 HcDev->PciIo,\r
1142 StatusRegAddr,\r
1143 &UhcStatus\r
1144 );\r
878ddf1f 1145 if (EFI_ERROR (Status)) {\r
1146 return EFI_DEVICE_ERROR;\r
1147 }\r
1148\r
1149 if (UhcCommand & USBCMD_EGSM) {\r
1150 *State = EfiUsbHcStateSuspend;\r
1151 return EFI_SUCCESS;\r
1152 }\r
1153\r
1154 if ((UhcStatus & USBSTS_HCH) == 0) {\r
1155 *State = EfiUsbHcStateOperational;\r
1156 } else {\r
1157 *State = EfiUsbHcStateHalt;\r
1158 }\r
1159\r
1160 return EFI_SUCCESS;\r
1161}\r
1162\r
1163\r
1164EFI_STATUS\r
1165EFIAPI\r
1166UHCISetState (\r
1167 IN EFI_USB_HC_PROTOCOL *This,\r
1168 IN EFI_USB_HC_STATE State\r
1169 )\r
1170/*++\r
1171 \r
1172 Routine Description:\r
1173 Sets the USB host controller to a specific state.\r
1174 \r
1175 Arguments:\r
1176 \r
1177 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1178\r
1179 State Indicates the state of the host controller that will be set.\r
1180 \r
1181 Returns:\r
1182 EFI_SUCCESS \r
1183 The USB host controller was successfully placed in the state \r
1184 specified by State.\r
1185 EFI_INVALID_PARAMETER \r
1186 State is invalid.\r
1187 EFI_DEVICE_ERROR \r
1188 Failed to set the state specified by State due to device error. \r
1189--*/\r
1190{\r
1191 USB_HC_DEV *HcDev;\r
1192 UINT32 CommandRegAddr;\r
1193 UINT32 StatusRegAddr;\r
1194 UINT16 Command;\r
1195 EFI_USB_HC_STATE CurrentState;\r
1196 EFI_STATUS Status;\r
1197\r
1198 HcDev = USB_HC_DEV_FROM_THIS (This);\r
1199\r
1200 CommandRegAddr = (UINT32) (USBCMD);\r
1201 StatusRegAddr = (UINT32) (USBSTS);\r
1202\r
1203 Status = UHCIGetState (This, &CurrentState);\r
1204 if (EFI_ERROR (Status)) {\r
1205 return EFI_DEVICE_ERROR;\r
1206 }\r
1207\r
1208 switch (State) {\r
1209\r
1210 case EfiUsbHcStateHalt:\r
1211 if (CurrentState == EfiUsbHcStateHalt) {\r
1212 return EFI_SUCCESS;\r
1213 }\r
1214\r
1215 Status = ReadUHCCommandReg (\r
562d2849 1216 HcDev->PciIo,\r
1217 CommandRegAddr,\r
1218 &Command\r
1219 );\r
878ddf1f 1220 if (EFI_ERROR (Status)) {\r
1221 return EFI_DEVICE_ERROR;\r
1222 }\r
1223\r
1224 Command &= ~USBCMD_RS;\r
1225\r
1226 Status = WriteUHCCommandReg (\r
562d2849 1227 HcDev->PciIo,\r
1228 CommandRegAddr,\r
1229 Command\r
1230 );\r
878ddf1f 1231 if (EFI_ERROR (Status)) {\r
1232 return EFI_DEVICE_ERROR;\r
1233 }\r
1234\r
1235 StatusRegAddr = (UINT32) (USBSTS);\r
1236 //\r
1237 // ensure the HC is in halt status after send the stop command\r
1238 //\r
1239 if (WaitForUHCHalt (HcDev->PciIo, StatusRegAddr, STALL_1_SECOND) == EFI_TIMEOUT) {\r
1240 return EFI_DEVICE_ERROR;\r
1241 }\r
1242 break;\r
1243\r
1244 case EfiUsbHcStateOperational:\r
1245 if (IsHostSysOrProcessErr (HcDev->PciIo, StatusRegAddr)) {\r
1246 return EFI_DEVICE_ERROR;\r
1247 }\r
1248\r
1249 switch (CurrentState) {\r
1250\r
1251 case EfiUsbHcStateOperational:\r
1252 return EFI_SUCCESS;\r
1253\r
1254 case EfiUsbHcStateHalt:\r
1255 //\r
1256 // Set Run/Stop bit to 1.\r
1257 //\r
1258 Status = ReadUHCCommandReg (\r
562d2849 1259 HcDev->PciIo,\r
1260 CommandRegAddr,\r
1261 &Command\r
1262 );\r
878ddf1f 1263 if (EFI_ERROR (Status)) {\r
1264 return EFI_DEVICE_ERROR;\r
1265 }\r
1266\r
1267 Command |= USBCMD_RS | USBCMD_MAXP;\r
1268 Status = WriteUHCCommandReg (\r
562d2849 1269 HcDev->PciIo,\r
1270 CommandRegAddr,\r
1271 Command\r
1272 );\r
878ddf1f 1273 if (EFI_ERROR (Status)) {\r
1274 return EFI_DEVICE_ERROR;\r
1275 }\r
1276\r
1277 break;\r
1278\r
1279 case EfiUsbHcStateSuspend:\r
1280 Status = ReadUHCCommandReg (\r
562d2849 1281 HcDev->PciIo,\r
1282 CommandRegAddr,\r
1283 &Command\r
1284 );\r
878ddf1f 1285 if (EFI_ERROR (Status)) {\r
1286 return EFI_DEVICE_ERROR;\r
1287 }\r
1288 \r
1289 //\r
1290 // FGR(Force Global Resume) bit is 0\r
1291 //\r
1292 if ((Command | (~USBCMD_FGR)) != 0xFF) {\r
1293 //\r
1294 // Write FGR bit to 1\r
1295 //\r
1296 Command |= USBCMD_FGR;\r
1297 WriteUHCCommandReg (\r
1298 HcDev->PciIo,\r
1299 CommandRegAddr,\r
1300 Command\r
1301 );\r
1302 }\r
1303 \r
1304 //\r
1305 // wait 20ms to let resume complete\r
1306 // (20ms is specified by UHCI spec)\r
1307 //\r
1308 gBS->Stall (FORCE_GLOBAL_RESUME_TIME);\r
1309\r
1310 //\r
1311 // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0\r
1312 //\r
1313 Command &= ~USBCMD_FGR;\r
1314 Command &= ~USBCMD_EGSM;\r
1315 Command |= USBCMD_RS;\r
1316 WriteUHCCommandReg (\r
1317 HcDev->PciIo,\r
1318 CommandRegAddr,\r
1319 Command\r
1320 );\r
1321 break;\r
1322\r
1323 default:\r
1324 break;\r
1325 }\r
1326 break;\r
1327\r
1328 case EfiUsbHcStateSuspend:\r
1329 if (CurrentState == EfiUsbHcStateSuspend) {\r
1330 return EFI_SUCCESS;\r
1331 }\r
1332\r
1333 Status = UHCISetState (This, EfiUsbHcStateHalt);\r
1334 if (EFI_ERROR (Status)) {\r
1335 return EFI_DEVICE_ERROR;\r
1336 }\r
1337 //\r
1338 // Set Enter Global Suspend Mode bit to 1.\r
1339 //\r
1340 Status = ReadUHCCommandReg (\r
562d2849 1341 HcDev->PciIo,\r
1342 CommandRegAddr,\r
1343 &Command\r
1344 );\r
878ddf1f 1345 if (EFI_ERROR (Status)) {\r
1346 return EFI_DEVICE_ERROR;\r
1347 }\r
1348\r
1349 Command |= USBCMD_EGSM;\r
1350 Status = WriteUHCCommandReg (\r
562d2849 1351 HcDev->PciIo,\r
1352 CommandRegAddr,\r
1353 Command\r
1354 );\r
878ddf1f 1355 if (EFI_ERROR (Status)) {\r
1356 return EFI_DEVICE_ERROR;\r
1357 }\r
1358 break;\r
1359\r
1360 default:\r
1361 return EFI_INVALID_PARAMETER;\r
1362 }\r
1363\r
1364 return EFI_SUCCESS;\r
1365}\r
1366\r
1367EFI_STATUS\r
1368EFIAPI\r
1369UHCIGetRootHubPortNumber (\r
1370 IN EFI_USB_HC_PROTOCOL *This,\r
1371 OUT UINT8 *PortNumber\r
1372 )\r
1373/*++\r
1374 \r
1375 Routine Description:\r
1376 Retrieves the number of root hub ports.\r
1377 \r
1378 Arguments:\r
1379 \r
1380 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1381 \r
1382 PortNumber A pointer to the number of the root hub ports.\r
1383 \r
1384 Returns:\r
1385 EFI_SUCCESS \r
1386 The port number was retrieved successfully.\r
1387 EFI_INVALID_PARAMETER \r
1388 PortNumber is NULL.\r
1389 EFI_DEVICE_ERROR \r
1390 An error was encountered while attempting to \r
1391 retrieve the port number. \r
1392--*/\r
1393{\r
1394 USB_HC_DEV *HcDev;\r
1395 UINT32 PSAddr;\r
1396 UINT16 RHPortControl;\r
1397 UINT32 Index;\r
1398 EFI_STATUS Status;\r
1399\r
1400 HcDev = USB_HC_DEV_FROM_THIS (This);\r
1401\r
1402 if (PortNumber == NULL) {\r
1403 return EFI_INVALID_PARAMETER;\r
1404 }\r
1405\r
1406 *PortNumber = 0;\r
1407\r
1408 for (Index = 0; Index < 2; Index++) {\r
1409 PSAddr = (UINT32) (USBPORTSC1 + Index * 2);\r
1410 Status = ReadRootPortReg (\r
562d2849 1411 HcDev->PciIo,\r
1412 PSAddr,\r
1413 &RHPortControl\r
1414 );\r
878ddf1f 1415 if (EFI_ERROR (Status)) {\r
1416 return EFI_DEVICE_ERROR;\r
1417 }\r
1418 //\r
1419 // Port Register content is valid\r
1420 //\r
1421 if (RHPortControl != 0xff) {\r
1422 (*PortNumber)++;\r
1423 }\r
1424 }\r
1425\r
1426 return EFI_SUCCESS;\r
1427}\r
1428\r
1429EFI_STATUS\r
1430EFIAPI\r
1431UHCIGetRootHubPortStatus (\r
1432 IN EFI_USB_HC_PROTOCOL *This,\r
1433 IN UINT8 PortNumber,\r
1434 OUT EFI_USB_PORT_STATUS *PortStatus\r
1435 )\r
1436/*++\r
1437 \r
1438 Routine Description:\r
1439 Retrieves the current status of a USB root hub port.\r
1440 \r
1441 Arguments:\r
1442 \r
1443 This A pointer to the EFI_USB_HC_PROTOCOL.\r
1444 \r
1445 PortNumber Specifies the root hub port from which the status \r
1446 is to be retrieved. This value is zero-based. For example, \r
1447 if a root hub has two ports, then the first port is numbered 0,\r
1448 and the second port is numbered 1.\r
1449 \r
1450 PortStatus A pointer to the current port status bits and \r
1451 port status change bits. \r
1452 \r
1453 Returns:\r
1454 EFI_SUCCESS \r
1455 The status of the USB root hub port specified by PortNumber \r
1456 was returned in PortStatus.\r
1457 EFI_INVALID_PARAMETER \r
1458 PortNumber is invalid. \r
1459 EFI_DEVICE_ERROR - Can't read register \r
1460--*/\r
1461{\r
1462 USB_HC_DEV *HcDev;\r
1463 UINT32 PSAddr;\r
1464 UINT16 RHPortStatus;\r
1465 UINT8 TotalPortNumber;\r
1466 EFI_STATUS Status;\r
1467\r
1468 if (PortStatus == NULL) {\r
1469 return EFI_INVALID_PARAMETER;\r
1470 }\r
1471\r
1472 UHCIGetRootHubPortNumber (This, &TotalPortNumber);\r
1473 if (PortNumber >= TotalPortNumber) {\r
1474 return EFI_INVALID_PARAMETER;\r
1475 }\r
1476\r
1477 HcDev = USB_HC_DEV_FROM_THIS (This);\r
1478 PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);\r
1479\r
1480 //\r
1481 // Clear port status\r
1482 //\r
1483 PortStatus->PortStatus = 0;\r
1484 PortStatus->PortChangeStatus = 0;\r
1485\r
1486 Status = ReadRootPortReg (\r
562d2849 1487 HcDev->PciIo,\r
1488 PSAddr,\r
1489 &RHPortStatus\r
1490 );\r
878ddf1f 1491\r
1492 if (EFI_ERROR (Status)) {\r
1493 return EFI_DEVICE_ERROR;\r
1494 }\r
1495 //\r
1496 // Fill Port Status bits\r
1497 //\r
1498 \r
1499 //\r
1500 // Current Connect Status\r
1501 //\r
1502 if (RHPortStatus & USBPORTSC_CCS) {\r
1503 PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;\r
1504 }\r
1505 //\r
1506 // Port Enabled/Disabled\r
1507 //\r
1508 if (RHPortStatus & USBPORTSC_PED) {\r
1509 PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;\r
1510 }\r
1511 \r
1512 //\r
1513 // Port Suspend\r
1514 //\r
1515 if (RHPortStatus & USBPORTSC_SUSP) {\r
1516 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
1517 }\r
1518 \r
1519 //\r
1520 // Port Reset\r
1521 //\r
1522 if (RHPortStatus & USBPORTSC_PR) {\r
1523 PortStatus->PortStatus |= USB_PORT_STAT_RESET;\r
1524 }\r
1525 \r
1526 //\r
1527 // Low Speed Device Attached\r
1528 //\r
1529 if (RHPortStatus & USBPORTSC_LSDA) {\r
1530 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
1531 }\r
1532 //\r
562d2849 1533 // CHC will always return one in this bit\r
1534 //\r
1535 PortStatus->PortStatus |= USB_PORT_STAT_OWNER;\r
1536 //\r
878ddf1f 1537 // Fill Port Status Change bits\r
1538 //\r
1539 \r
1540 //\r
1541 // Connect Status Change\r
1542 //\r
1543 if (RHPortStatus & USBPORTSC_CSC) {\r
1544 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;\r
1545 }\r
1546 \r
1547 //\r
1548 // Port Enabled/Disabled Change\r
1549 //\r
1550 if (RHPortStatus & USBPORTSC_PEDC) {\r
1551 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;\r
1552 }\r
1553\r
1554 return EFI_SUCCESS;\r
1555}\r
1556\r
1557EFI_STATUS\r
1558EFIAPI\r
1559UHCISetRootHubPortFeature (\r
1560 IN EFI_USB_HC_PROTOCOL *This,\r
1561 IN UINT8 PortNumber,\r
1562 IN EFI_USB_PORT_FEATURE PortFeature\r
1563 )\r
1564/*++\r
1565 \r
1566 Routine Description:\r
1567 Sets a feature for the specified root hub port.\r
1568 \r
1569 Arguments:\r
1570 \r
1571 This A pointer to the EFI_USB_HC_PROTOCOL.\r
1572 \r
1573 PortNumber Specifies the root hub port whose feature \r
1574 is requested to be set.\r
1575 \r
1576 PortFeature Indicates the feature selector associated \r
1577 with the feature set request. \r
1578 \r
1579 Returns:\r
1580 EFI_SUCCESS \r
1581 The feature specified by PortFeature was set for the \r
1582 USB root hub port specified by PortNumber.\r
1583 EFI_INVALID_PARAMETER \r
1584 PortNumber is invalid or PortFeature is invalid.\r
1585 EFI_DEVICE_ERROR\r
1586 Can't read register\r
1587--*/\r
1588{\r
1589 USB_HC_DEV *HcDev;\r
1590 UINT32 PSAddr;\r
1591 UINT32 CommandRegAddr;\r
1592 //\r
1593 // root hub port status\r
1594 //\r
1595 UINT16 RHPortControl;\r
1596 UINT16 Command;\r
1597 UINT8 TotalPortNumber;\r
1598 EFI_STATUS Status;\r
1599\r
1600 UHCIGetRootHubPortNumber (This, &TotalPortNumber);\r
1601 if (PortNumber >= TotalPortNumber) {\r
1602 return EFI_INVALID_PARAMETER;\r
1603 }\r
1604\r
1605 HcDev = USB_HC_DEV_FROM_THIS (This);\r
1606\r
1607 PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);\r
1608 CommandRegAddr = (UINT32) (USBCMD);\r
1609\r
1610 Status = ReadRootPortReg (\r
1611 HcDev->PciIo,\r
1612 PSAddr,\r
1613 &RHPortControl\r
1614 );\r
1615 if (EFI_ERROR (Status)) {\r
1616 return EFI_DEVICE_ERROR;\r
1617 }\r
1618\r
1619 switch (PortFeature) {\r
1620\r
1621 case EfiUsbPortSuspend:\r
1622 Status = ReadUHCCommandReg (\r
562d2849 1623 HcDev->PciIo,\r
1624 CommandRegAddr,\r
1625 &Command\r
1626 );\r
878ddf1f 1627 if (EFI_ERROR (Status)) {\r
1628 return EFI_DEVICE_ERROR;\r
1629 }\r
1630\r
1631 if (!(Command & USBCMD_EGSM)) {\r
1632 //\r
1633 // if global suspend is not active, can set port suspend\r
1634 //\r
1635 RHPortControl &= 0xfff5;\r
1636 RHPortControl |= USBPORTSC_SUSP;\r
1637 }\r
1638 break;\r
1639\r
1640 case EfiUsbPortReset:\r
1641 RHPortControl &= 0xfff5;\r
1642 //\r
1643 // Set the reset bit\r
1644 //\r
1645 RHPortControl |= USBPORTSC_PR;\r
1646 break;\r
1647\r
1648 case EfiUsbPortPower:\r
1649 break;\r
1650\r
1651 case EfiUsbPortEnable:\r
1652 RHPortControl &= 0xfff5;\r
1653 RHPortControl |= USBPORTSC_PED;\r
1654 break;\r
1655\r
1656 default:\r
1657 return EFI_INVALID_PARAMETER;\r
1658 }\r
1659\r
1660 WriteRootPortReg (\r
1661 HcDev->PciIo,\r
1662 PSAddr,\r
1663 RHPortControl\r
1664 );\r
1665\r
1666 return EFI_SUCCESS;\r
1667}\r
1668\r
1669EFI_STATUS\r
1670EFIAPI\r
1671UHCIClearRootHubPortFeature (\r
1672 IN EFI_USB_HC_PROTOCOL *This,\r
1673 IN UINT8 PortNumber,\r
1674 IN EFI_USB_PORT_FEATURE PortFeature\r
1675 )\r
1676/*++\r
1677 \r
1678 Routine Description:\r
1679 Clears a feature for the specified root hub port.\r
1680 \r
1681 Arguments:\r
1682 \r
1683 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1684 \r
1685 PortNumber Specifies the root hub port whose feature \r
1686 is requested to be cleared.\r
1687 \r
1688 PortFeature Indicates the feature selector associated with the \r
1689 feature clear request.\r
1690 \r
1691 Returns:\r
1692 EFI_SUCCESS \r
1693 The feature specified by PortFeature was cleared for the \r
1694 USB root hub port specified by PortNumber.\r
1695 EFI_INVALID_PARAMETER \r
1696 PortNumber is invalid or PortFeature is invalid.\r
1697 EFI_DEVICE_ERROR\r
1698 Can't read register\r
1699--*/\r
1700{\r
1701 USB_HC_DEV *HcDev;\r
1702 UINT32 PSAddr;\r
1703 UINT16 RHPortControl;\r
1704 UINT8 TotalPortNumber;\r
1705 EFI_STATUS Status;\r
1706\r
1707 UHCIGetRootHubPortNumber (This, &TotalPortNumber);\r
1708\r
1709 if (PortNumber >= TotalPortNumber) {\r
1710 return EFI_INVALID_PARAMETER;\r
1711 }\r
1712\r
1713 HcDev = USB_HC_DEV_FROM_THIS (This);\r
1714 PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);\r
1715\r
1716 Status = ReadRootPortReg (\r
562d2849 1717 HcDev->PciIo,\r
1718 PSAddr,\r
1719 &RHPortControl\r
1720 );\r
878ddf1f 1721 if (EFI_ERROR (Status)) {\r
1722 return EFI_DEVICE_ERROR;\r
1723 }\r
1724\r
1725 switch (PortFeature) {\r
1726 //\r
1727 // clear PORT_ENABLE feature means disable port.\r
1728 //\r
1729 case EfiUsbPortEnable:\r
1730 RHPortControl &= 0xfff5;\r
1731 RHPortControl &= ~USBPORTSC_PED;\r
1732 break;\r
1733\r
1734 //\r
1735 // clear PORT_SUSPEND feature means resume the port.\r
1736 // (cause a resume on the specified port if in suspend mode)\r
1737 //\r
1738 case EfiUsbPortSuspend:\r
1739 RHPortControl &= 0xfff5;\r
1740 RHPortControl &= ~USBPORTSC_SUSP;\r
1741 break;\r
1742\r
1743 //\r
1744 // no operation\r
1745 //\r
1746 case EfiUsbPortPower:\r
1747 break;\r
1748\r
1749 //\r
1750 // clear PORT_RESET means clear the reset signal.\r
1751 //\r
1752 case EfiUsbPortReset:\r
1753 RHPortControl &= 0xfff5;\r
1754 RHPortControl &= ~USBPORTSC_PR;\r
1755 break;\r
1756\r
1757 //\r
1758 // clear connect status change\r
1759 //\r
1760 case EfiUsbPortConnectChange:\r
1761 RHPortControl &= 0xfff5;\r
1762 RHPortControl |= USBPORTSC_CSC;\r
1763 break;\r
1764\r
1765 //\r
1766 // clear enable/disable status change\r
1767 //\r
1768 case EfiUsbPortEnableChange:\r
1769 RHPortControl &= 0xfff5;\r
1770 RHPortControl |= USBPORTSC_PEDC;\r
1771 break;\r
1772\r
1773 //\r
1774 // root hub does not support this request\r
1775 //\r
1776 case EfiUsbPortSuspendChange:\r
1777 break;\r
1778\r
1779 //\r
1780 // root hub does not support this request\r
1781 //\r
1782 case EfiUsbPortOverCurrentChange:\r
1783 break;\r
1784\r
1785 //\r
1786 // root hub does not support this request\r
1787 //\r
1788 case EfiUsbPortResetChange:\r
1789 break;\r
1790\r
1791 default:\r
1792 return EFI_INVALID_PARAMETER;\r
1793 }\r
1794\r
1795 WriteRootPortReg (\r
1796 HcDev->PciIo,\r
1797 PSAddr,\r
1798 RHPortControl\r
1799 );\r
1800\r
1801 return EFI_SUCCESS;\r
1802}\r
1803\r
1804EFI_STATUS\r
1805EFIAPI\r
1806UHCIControlTransfer (\r
1807 IN EFI_USB_HC_PROTOCOL *This,\r
1808 IN UINT8 DeviceAddress,\r
1809 IN BOOLEAN IsSlowDevice,\r
1810 IN UINT8 MaximumPacketLength,\r
1811 IN EFI_USB_DEVICE_REQUEST *Request,\r
1812 IN EFI_USB_DATA_DIRECTION TransferDirection,\r
1813 IN OUT VOID *Data, OPTIONAL\r
1814 IN OUT UINTN *DataLength, OPTIONAL\r
1815 IN UINTN TimeOut,\r
1816 OUT UINT32 *TransferResult\r
1817 )\r
1818/*++\r
1819 \r
1820 Routine Description:\r
1821 Submits control transfer to a target USB device.\r
1822 \r
1823 Arguments:\r
1824 \r
1825 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1826\r
1827 DeviceAddress Represents the address of the target device on the USB,\r
1828 which is assigned during USB enumeration.\r
1829\r
1830 IsSlowDevice Indicates whether the target device is slow device \r
1831 or full-speed device.\r
1832 \r
1833 MaximumPacketLength Indicates the maximum packet size that the \r
1834 default control transfer endpoint is capable of \r
1835 sending or receiving.\r
1836 \r
1837 Request A pointer to the USB device request that will be sent \r
1838 to the USB device. \r
1839 \r
1840 TransferDirection Specifies the data direction for the transfer.\r
1841 There are three values available, DataIn, DataOut \r
1842 and NoData.\r
1843 \r
1844 Data A pointer to the buffer of data that will be transmitted \r
1845 to USB device or received from USB device.\r
1846 \r
1847 DataLength Indicates the size, in bytes, of the data buffer \r
1848 specified by Data.\r
1849 \r
1850 TimeOut Indicates the maximum time, in microseconds, \r
1851 which the transfer is allowed to complete.\r
1852 \r
1853 TransferResult A pointer to the detailed result information generated \r
1854 by this control transfer.\r
1855 \r
1856 Returns:\r
1857 EFI_SUCCESS \r
1858 The control transfer was completed successfully.\r
1859 EFI_OUT_OF_RESOURCES \r
1860 The control transfer could not be completed due to a lack of resources.\r
1861 EFI_INVALID_PARAMETER \r
1862 Some parameters are invalid.\r
1863 EFI_TIMEOUT \r
1864 The control transfer failed due to timeout.\r
1865 EFI_DEVICE_ERROR \r
1866 The control transfer failed due to host controller or device error. \r
1867 Caller should check TranferResult for detailed error information.\r
1868\r
1869--*/\r
1870{\r
1871 USB_HC_DEV *HcDev;\r
1872 UINT32 StatusReg;\r
1873 UINT32 FrameNumReg;\r
1874 UINT8 PktID;\r
1875 QH_STRUCT *PtrQH;\r
1876 TD_STRUCT *PtrTD;\r
1877 TD_STRUCT *PtrPreTD;\r
1878 TD_STRUCT *PtrSetupTD;\r
1879 TD_STRUCT *PtrStatusTD;\r
1880 EFI_STATUS Status;\r
1881 UINTN Index;\r
1882 UINTN DataLen;\r
1883 UINT8 *PtrDataSource;\r
1884 UINT8 *Ptr;\r
1885 UINT8 DataToggle;\r
1886 UINT16 LoadFrameListIndex;\r
1887 UINT8 PktSize;\r
1888\r
1889 UINT8 *RequestMappedAddress;\r
1890 VOID *RequestMapping;\r
1891 UINTN RequestLen;\r
1892\r
1893 EFI_PHYSICAL_ADDRESS TempPtr;\r
1894 VOID *Mapping;\r
1895\r
1896 TD_STRUCT *PtrFirstDataTD;\r
1897 TD_STRUCT *ptrLastDataTD;\r
1898 BOOLEAN FirstTD;\r
1899\r
1900 FirstTD = FALSE;\r
1901 RequestMappedAddress = NULL;\r
1902 RequestMapping = NULL;\r
1903 Mapping = NULL;\r
1904 PtrFirstDataTD = NULL;\r
1905 ptrLastDataTD = NULL;\r
1906 PktID = INPUT_PACKET_ID;\r
1907 Mapping = NULL;\r
1908 HcDev = USB_HC_DEV_FROM_THIS (This);\r
1909 StatusReg = (UINT32) (USBSTS);\r
1910 FrameNumReg = (UINT32) (USBFRNUM);\r
1911 PtrPreTD = NULL;\r
1912 PtrTD = NULL;\r
1913\r
1914 //\r
1915 // Parameters Checking\r
1916 //\r
1917 if (Request == NULL || TransferResult == NULL) {\r
1918 return EFI_INVALID_PARAMETER;\r
1919 }\r
1920 \r
1921 //\r
1922 // if errors exist that cause host controller halt,\r
1923 // then return EFI_DEVICE_ERROR.\r
1924 //\r
1925 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
1926\r
1927 ClearStatusReg (HcDev->PciIo, StatusReg);\r
1928 *TransferResult = EFI_USB_ERR_SYSTEM;\r
1929 return EFI_DEVICE_ERROR;\r
1930 }\r
1931 \r
1932 //\r
1933 // low speed usb devices are limited to only an eight-byte\r
1934 // maximum data payload size\r
1935 //\r
1936 if (IsSlowDevice && (MaximumPacketLength != 8)) {\r
1937 return EFI_INVALID_PARAMETER;\r
1938 }\r
1939\r
1940 if (MaximumPacketLength != 8 && \r
1941 MaximumPacketLength != 16 &&\r
1942 MaximumPacketLength != 32 &&\r
1943 MaximumPacketLength != 64) {\r
1944 return EFI_INVALID_PARAMETER;\r
1945 }\r
1946\r
1947 if ((TransferDirection != EfiUsbNoData) && (DataLength == NULL)) {\r
1948 return EFI_INVALID_PARAMETER;\r
1949 }\r
1950\r
1951 switch (TransferDirection) {\r
1952\r
1953 case EfiUsbDataIn:\r
1954 PktID = INPUT_PACKET_ID;\r
1955 PtrDataSource = Data;\r
1956 DataLen = *DataLength;\r
1957\r
1958 //\r
1959 // map the source data buffer for bus master access.\r
1960 // BusMasterWrite means cpu read\r
1961 //\r
1962 Status = HcDev->PciIo->Map (\r
562d2849 1963 HcDev->PciIo,\r
1964 EfiPciIoOperationBusMasterWrite,\r
1965 PtrDataSource,\r
1966 &DataLen,\r
1967 &TempPtr,\r
1968 &Mapping\r
1969 );\r
878ddf1f 1970 if (EFI_ERROR (Status)) {\r
1971 return Status;\r
1972 }\r
1973\r
1974 Ptr = (UINT8 *) ((UINTN) TempPtr);\r
1975 break;\r
1976\r
1977 case EfiUsbDataOut:\r
1978 PktID = OUTPUT_PACKET_ID;\r
1979 PtrDataSource = Data;\r
1980 DataLen = *DataLength;\r
1981\r
1982 //\r
1983 // map the source data buffer for bus master access.\r
1984 // BusMasterRead means cpu write\r
1985 //\r
1986 Status = HcDev->PciIo->Map (\r
562d2849 1987 HcDev->PciIo,\r
1988 EfiPciIoOperationBusMasterRead,\r
1989 PtrDataSource,\r
1990 &DataLen,\r
1991 &TempPtr,\r
1992 &Mapping\r
1993 );\r
878ddf1f 1994 if (EFI_ERROR (Status)) {\r
1995 return Status;\r
1996 }\r
1997\r
1998 Ptr = (UINT8 *) ((UINTN) TempPtr);\r
1999 break;\r
2000\r
2001 //\r
2002 // no data stage\r
2003 //\r
2004 case EfiUsbNoData:\r
2005 if ((DataLength != NULL) && (*DataLength != 0)) {\r
2006 return EFI_INVALID_PARAMETER;\r
2007 }\r
2008\r
2009 PktID = OUTPUT_PACKET_ID;\r
2010 PtrDataSource = NULL;\r
2011 DataLen = 0;\r
2012 Ptr = NULL;\r
2013 break;\r
2014\r
2015 default:\r
2016 return EFI_INVALID_PARAMETER;\r
2017 }\r
2018\r
2019 Status = ClearStatusReg (HcDev->PciIo, StatusReg);\r
2020 if (EFI_ERROR (Status)) {\r
2021 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2022 return EFI_DEVICE_ERROR;\r
2023 }\r
2024 //\r
2025 // create QH structure and init\r
2026 //\r
2027 Status = CreateQH (HcDev, &PtrQH);\r
2028 if (EFI_ERROR (Status)) {\r
2029 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2030 return Status;\r
2031 }\r
2032 \r
2033 //\r
2034 // map the Request for bus master access.\r
2035 // BusMasterRead means cpu write\r
2036 //\r
2037 RequestLen = sizeof (EFI_USB_DEVICE_REQUEST);\r
2038 Status = HcDev->PciIo->Map (\r
562d2849 2039 HcDev->PciIo,\r
2040 EfiPciIoOperationBusMasterRead,\r
2041 (UINT8 *) Request,\r
2042 &RequestLen,\r
2043 &TempPtr,\r
2044 &RequestMapping\r
2045 );\r
878ddf1f 2046\r
2047 if (EFI_ERROR (Status)) {\r
2048 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2049 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
2050 return Status;\r
2051 }\r
2052\r
2053 RequestMappedAddress = (UINT8 *) ((UINTN) TempPtr);\r
2054\r
2055 //\r
2056 // generate Setup Stage TD\r
2057 //\r
2058 Status = GenSetupStageTD (\r
562d2849 2059 HcDev,\r
2060 DeviceAddress,\r
2061 0,\r
2062 IsSlowDevice,\r
2063 (UINT8 *) RequestMappedAddress,\r
2064 sizeof (EFI_USB_DEVICE_REQUEST),\r
2065 &PtrSetupTD\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 HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);\r
2072 return Status;\r
2073 }\r
2074 \r
2075 //\r
2076 // Data Stage of Control Transfer\r
2077 //\r
2078 DataToggle = 1;\r
2079 FirstTD = TRUE;\r
2080 while (DataLen > 0) {\r
2081 //\r
2082 // create TD structures and link together\r
2083 //\r
2084 \r
2085 //\r
2086 // PktSize is the data load size that each TD carries.\r
2087 //\r
2088 PktSize = (UINT8) DataLen;\r
2089 if (DataLen > MaximumPacketLength) {\r
2090 PktSize = MaximumPacketLength;\r
2091 }\r
2092\r
2093 Status = GenDataTD (\r
562d2849 2094 HcDev,\r
2095 DeviceAddress,\r
2096 0,\r
2097 Ptr,\r
2098 PktSize,\r
2099 PktID,\r
2100 DataToggle,\r
2101 IsSlowDevice,\r
2102 &PtrTD\r
2103 );\r
878ddf1f 2104\r
2105 if (EFI_ERROR (Status)) {\r
2106 //\r
2107 // free all resources occupied\r
2108 //\r
2109 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2110 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
2111 HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);\r
2112 DeleteQueuedTDs (HcDev, PtrSetupTD);\r
2113 DeleteQueuedTDs (HcDev, PtrFirstDataTD);\r
2114 return Status;\r
2115 }\r
2116 \r
2117 //\r
2118 // Link two TDs in vertical depth\r
2119 //\r
2120 if (FirstTD) {\r
2121 PtrFirstDataTD = PtrTD;\r
2122 PtrFirstDataTD->ptrNextTD = NULL;\r
2123 FirstTD = FALSE;\r
2124 } else {\r
2125 LinkTDToTD (PtrPreTD, PtrTD);\r
2126 }\r
2127\r
2128 PtrPreTD = PtrTD;\r
2129\r
2130 DataToggle ^= 1;\r
2131 Ptr += PktSize;\r
2132 DataLen -= PktSize;\r
2133 }\r
2134\r
2135 ptrLastDataTD = PtrTD;\r
2136\r
2137 //\r
2138 // Status Stage of Control Transfer\r
2139 //\r
2140 if (PktID == OUTPUT_PACKET_ID) {\r
2141 PktID = INPUT_PACKET_ID;\r
2142 } else {\r
2143 PktID = OUTPUT_PACKET_ID;\r
2144 }\r
2145 \r
2146 //\r
2147 // create Status Stage TD structure\r
2148 //\r
2149 Status = CreateStatusTD (\r
562d2849 2150 HcDev,\r
2151 DeviceAddress,\r
2152 0,\r
2153 PktID,\r
2154 IsSlowDevice,\r
2155 &PtrStatusTD\r
2156 );\r
878ddf1f 2157\r
2158 if (EFI_ERROR (Status)) {\r
2159 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2160 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
2161 HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);\r
2162 DeleteQueuedTDs (HcDev, PtrSetupTD);\r
2163 DeleteQueuedTDs (HcDev, PtrFirstDataTD);\r
2164 return Status;\r
2165 }\r
2166\r
2167 if (IsSlowDevice) {\r
2168 //\r
2169 // link setup TD structures to QH structure\r
2170 //\r
2171 LinkTDToQH (PtrQH, PtrSetupTD);\r
2172\r
2173 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
2174\r
2175 //\r
2176 // link QH-TDs to total 100 frame list entry to speed up the execution.\r
2177 //\r
2178 for (Index = 0; Index < 100; Index++) {\r
2179 LinkQHToFrameList (\r
2180 HcDev->FrameListEntry,\r
2181 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
2182 PtrQH\r
2183 );\r
2184 }\r
2185 //\r
2186 // Poll QH-TDs execution and get result.\r
2187 // detail status is returned\r
2188 //\r
2189 Status = ExecuteControlTransfer (\r
2190 HcDev,\r
2191 PtrSetupTD,\r
2192 LoadFrameListIndex,\r
2193 DataLength,\r
2194 TimeOut,\r
2195 TransferResult\r
2196 );\r
2197 //\r
2198 // Remove Control Transfer QH-TDs structure from the frame list\r
2199 // and update the pointers in the Frame List\r
2200 // and other pointers in other related QH structures.\r
2201 //\r
2202 for (Index = 0; Index < 100; Index++) {\r
2203 DelLinkSingleQH (\r
2204 HcDev,\r
2205 PtrQH,\r
2206 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
2207 FALSE,\r
2208 FALSE\r
2209 );\r
2210 }\r
2211 //\r
2212 // delete setup stage TD; the QH is reserved for the next stages.\r
2213 //\r
2214 DeleteQueuedTDs (HcDev, PtrSetupTD);\r
2215\r
2216 //\r
2217 // if setup stage error, return error\r
2218 //\r
2219 if (EFI_ERROR (Status)) {\r
2220 goto Done;\r
2221 }\r
2222 //\r
2223 // some control transfers do not have Data Stage\r
2224 //\r
2225 if (PtrFirstDataTD != NULL) {\r
2226\r
2227 LinkTDToQH (PtrQH, PtrFirstDataTD);\r
2228 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
2229\r
2230 for (Index = 0; Index < 500; Index++) {\r
2231 LinkQHToFrameList (\r
2232 HcDev->FrameListEntry,\r
2233 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
2234 PtrQH\r
2235 );\r
2236 }\r
2237\r
2238 Status = ExecuteControlTransfer (\r
562d2849 2239 HcDev,\r
2240 PtrFirstDataTD,\r
2241 LoadFrameListIndex,\r
2242 DataLength,\r
2243 TimeOut,\r
2244 TransferResult\r
2245 );\r
878ddf1f 2246\r
2247 for (Index = 0; Index < 500; Index++) {\r
2248 DelLinkSingleQH (\r
2249 HcDev,\r
2250 PtrQH,\r
2251 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
2252 FALSE,\r
2253 FALSE\r
2254 );\r
2255 }\r
2256 //\r
2257 // delete data stage TD; the QH is reserved for the next stage.\r
2258 //\r
2259 DeleteQueuedTDs (HcDev, PtrFirstDataTD);\r
2260 }\r
2261 //\r
2262 // if data stage error, goto done and return error\r
2263 //\r
2264 if (EFI_ERROR (Status)) {\r
2265 goto Done;\r
2266 }\r
2267\r
2268 LinkTDToQH (PtrQH, PtrStatusTD);\r
2269 //\r
2270 // get the frame list index that the QH-TDs will be linked to.\r
2271 //\r
2272 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
2273\r
2274 for (Index = 0; Index < 100; Index++) {\r
2275 //\r
2276 // put the QH-TDs directly or indirectly into the proper place\r
2277 // in the Frame List\r
2278 //\r
2279 LinkQHToFrameList (\r
2280 HcDev->FrameListEntry,\r
2281 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
2282 PtrQH\r
2283 );\r
2284 }\r
2285 //\r
2286 // Poll QH-TDs execution and get result.\r
2287 // detail status is returned\r
2288 //\r
2289 Status = ExecuteControlTransfer (\r
562d2849 2290 HcDev,\r
2291 PtrStatusTD,\r
2292 LoadFrameListIndex,\r
2293 DataLength,\r
2294 TimeOut,\r
2295 TransferResult\r
2296 );\r
878ddf1f 2297\r
2298 //\r
2299 // Delete Control Transfer QH-TDs structure\r
2300 // and update the pointers in the Frame List\r
2301 // and other pointers in other related QH structures.\r
2302 //\r
2303 // TRUE means must search other framelistindex\r
2304 //\r
2305 for (Index = 0; Index < 100; Index++) {\r
2306 DelLinkSingleQH (\r
2307 HcDev,\r
2308 PtrQH,\r
2309 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
2310 FALSE,\r
2311 FALSE\r
2312 );\r
2313 }\r
2314\r
2315 DeleteQueuedTDs (HcDev, PtrStatusTD);\r
2316\r
2317 } else {\r
2318 //\r
2319 // link setup stage TD with data stage TD\r
2320 //\r
2321 PtrPreTD = PtrSetupTD;\r
2322 if (PtrFirstDataTD != NULL) {\r
2323 LinkTDToTD (PtrSetupTD, PtrFirstDataTD);\r
2324 PtrPreTD = ptrLastDataTD;\r
2325 }\r
2326 //\r
2327 // link status TD with previous TD\r
2328 //\r
2329 LinkTDToTD (PtrPreTD, PtrStatusTD);\r
2330\r
2331 //\r
2332 // link QH with TD\r
2333 //\r
2334 LinkTDToQH (PtrQH, PtrSetupTD);\r
2335\r
2336 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
2337 for (Index = 0; Index < 500; Index++) {\r
2338 //\r
2339 // put the QH-TDs directly or indirectly into the proper place\r
2340 // in the Frame List\r
2341 //\r
2342 LinkQHToFrameList (\r
2343 HcDev->FrameListEntry,\r
2344 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
2345 PtrQH\r
2346 );\r
2347 }\r
2348 //\r
2349 // Poll QH-TDs execution and get result.\r
2350 // detail status is returned\r
2351 //\r
2352 Status = ExecuteControlTransfer (\r
562d2849 2353 HcDev,\r
2354 PtrSetupTD,\r
2355 LoadFrameListIndex,\r
2356 DataLength,\r
2357 TimeOut,\r
2358 TransferResult\r
2359 );\r
878ddf1f 2360 //\r
2361 // Remove Control Transfer QH-TDs structure from the frame list\r
2362 // and update the pointers in the Frame List\r
2363 // and other pointers in other related QH structures.\r
2364 //\r
2365 for (Index = 0; Index < 500; Index++) {\r
2366 DelLinkSingleQH (\r
2367 HcDev,\r
2368 PtrQH,\r
2369 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
2370 FALSE,\r
2371 FALSE\r
2372 );\r
2373 }\r
2374\r
2375 DeleteQueuedTDs (HcDev, PtrSetupTD);\r
2376 }\r
2377\r
2378Done:\r
2379\r
2380 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
2381\r
2382 if (Mapping != NULL) {\r
2383 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2384 }\r
2385\r
2386 if (RequestMapping != NULL) {\r
2387 HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);\r
2388 }\r
2389 //\r
2390 // if has errors that cause host controller halt,\r
2391 // then return EFI_DEVICE_ERROR directly.\r
2392 //\r
2393 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
2394\r
2395 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2396 *TransferResult |= EFI_USB_ERR_SYSTEM;\r
2397 return EFI_DEVICE_ERROR;\r
2398 }\r
2399\r
2400 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2401 HcDev->PciIo->Flush (HcDev->PciIo);\r
2402 return Status;\r
2403}\r
2404\r
2405EFI_STATUS\r
2406EFIAPI\r
2407UHCIBulkTransfer (\r
2408 IN EFI_USB_HC_PROTOCOL *This,\r
2409 IN UINT8 DeviceAddress,\r
2410 IN UINT8 EndPointAddress,\r
2411 IN UINT8 MaximumPacketLength,\r
2412 IN OUT VOID *Data,\r
2413 IN OUT UINTN *DataLength,\r
2414 IN OUT UINT8 *DataToggle,\r
2415 IN UINTN TimeOut,\r
2416 OUT UINT32 *TransferResult\r
2417 )\r
2418/*++\r
2419 \r
2420 Routine Description:\r
2421 Submits bulk transfer to a bulk endpoint of a USB device.\r
2422 \r
2423 Arguments:\r
2424 \r
2425 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
2426 \r
2427 DeviceAddress Represents the address of the target device on the USB,\r
2428 which is assigned during USB enumeration.\r
2429 EndPointAddress The combination of an endpoint number and an \r
2430 endpoint direction of the target USB device. \r
2431 Each endpoint address supports data transfer in \r
2432 one direction except the control endpoint \r
2433 (whose default endpoint address is 0). \r
2434 It is the caller's responsibility to make sure that \r
2435 the EndPointAddress represents a bulk endpoint. \r
2436 \r
2437 MaximumPacketLength Indicates the maximum packet size the target endpoint\r
2438 is capable of sending or receiving.\r
2439 \r
2440 Data A pointer to the buffer of data that will be transmitted \r
2441 to USB device or received from USB device.\r
2442 DataLength When input, indicates the size, in bytes, of the data buffer\r
2443 specified by Data. When output, indicates the actually \r
2444 transferred data size.\r
2445 \r
2446 DataToggle A pointer to the data toggle value. On input, it indicates \r
2447 the initial data toggle value the bulk transfer should adopt;\r
2448 on output, it is updated to indicate the data toggle value \r
2449 of the subsequent bulk transfer. \r
2450 \r
2451 TimeOut Indicates the maximum time, in microseconds, which the \r
2452 transfer is allowed to complete.\r
2453 \r
2454 TransferResult A pointer to the detailed result information of the \r
2455 bulk transfer.\r
2456\r
2457 Returns:\r
2458 EFI_SUCCESS \r
2459 The bulk transfer was completed successfully.\r
2460 EFI_OUT_OF_RESOURCES \r
2461 The bulk transfer could not be submitted due to lack of resource.\r
2462 EFI_INVALID_PARAMETER \r
2463 Some parameters are invalid.\r
2464 EFI_TIMEOUT \r
2465 The bulk transfer failed due to timeout.\r
2466 EFI_DEVICE_ERROR \r
2467 The bulk transfer failed due to host controller or device error.\r
2468 Caller should check TranferResult for detailed error information.\r
2469\r
2470--*/\r
2471{\r
2472 USB_HC_DEV *HcDev;\r
2473 UINT32 StatusReg;\r
2474 UINT32 FrameNumReg;\r
2475 UINTN DataLen;\r
2476 QH_STRUCT *PtrQH;\r
2477 TD_STRUCT *PtrFirstTD;\r
2478 TD_STRUCT *PtrTD;\r
2479 TD_STRUCT *PtrPreTD;\r
2480 UINT16 LoadFrameListIndex;\r
2481 UINT16 SavedFrameListIndex;\r
2482 UINT8 PktID;\r
2483 UINT8 *PtrDataSource;\r
2484 UINT8 *Ptr;\r
2485 BOOLEAN IsFirstTD;\r
2486 EFI_STATUS Status;\r
2487 UINT32 Index;\r
2488 UINT8 PktSize;\r
2489\r
2490 EFI_USB_DATA_DIRECTION TransferDirection;\r
2491 //\r
2492 // Used to calculate how many entries are linked to the\r
2493 // specified bulk transfer QH-TDs\r
2494 //\r
2495 UINT32 LinkTimes;\r
2496\r
2497 BOOLEAN ShortPacketEnable;\r
2498 EFI_PHYSICAL_ADDRESS TempPtr;\r
2499 VOID *Mapping;\r
2500\r
2501 HcDev = USB_HC_DEV_FROM_THIS (This);\r
2502 StatusReg = (UINT32) (USBSTS);\r
2503 FrameNumReg = (UINT32) (USBFRNUM);\r
2504 PktID = INPUT_PACKET_ID;\r
2505 PtrTD = NULL;\r
2506 PtrFirstTD = NULL;\r
2507 PtrPreTD = NULL;\r
2508 LinkTimes = 1;\r
2509 DataLen = 0;\r
2510 Ptr = NULL;\r
2511 ShortPacketEnable = FALSE;\r
2512 Mapping = NULL;\r
2513\r
2514 //\r
2515 // Parameters Checking\r
2516 //\r
2517 \r
2518 if ((DataLength == NULL) ||\r
2519 (Data == NULL) ||\r
2520 (TransferResult == NULL)) {\r
2521 return EFI_INVALID_PARAMETER;\r
2522 }\r
2523 \r
2524 //\r
2525 // if has errors that cause host controller halt,\r
2526 // then return EFI_DEVICE_ERROR directly.\r
2527 //\r
2528 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
2529\r
2530 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2531 *TransferResult = EFI_USB_ERR_SYSTEM;\r
2532 return EFI_DEVICE_ERROR;\r
2533 }\r
2534\r
2535 if (*DataLength == 0) {\r
2536 return EFI_INVALID_PARAMETER;\r
2537 }\r
2538\r
2539 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
2540 return EFI_INVALID_PARAMETER;\r
2541 }\r
2542\r
2543 if (MaximumPacketLength != 8 &&\r
2544 MaximumPacketLength != 16 &&\r
2545 MaximumPacketLength != 32 &&\r
2546 MaximumPacketLength != 64) {\r
2547 return EFI_INVALID_PARAMETER;\r
2548 }\r
2549 \r
2550 //\r
2551 // Enable the maximum packet size (64bytes)\r
2552 // that can be used for full speed bandwidth reclamation\r
2553 // at the end of a frame.\r
2554 //\r
2555 EnableMaxPacketSize (HcDev);\r
2556\r
2557 Status = ClearStatusReg (HcDev->PciIo, StatusReg);\r
2558 if (EFI_ERROR (Status)) {\r
2559 return EFI_DEVICE_ERROR;\r
2560 }\r
2561 \r
2562 //\r
2563 // construct QH and TD data structures,\r
2564 // and link them together\r
2565 //\r
2566 if (EndPointAddress & 0x80) {\r
2567 TransferDirection = EfiUsbDataIn;\r
2568 } else {\r
2569 TransferDirection = EfiUsbDataOut;\r
2570 }\r
2571\r
2572 switch (TransferDirection) {\r
2573\r
2574 case EfiUsbDataIn:\r
2575 ShortPacketEnable = TRUE;\r
2576 PktID = INPUT_PACKET_ID;\r
2577 PtrDataSource = Data;\r
2578 DataLen = *DataLength;\r
2579\r
2580 //\r
2581 // BusMasterWrite means cpu read\r
2582 //\r
2583 Status = HcDev->PciIo->Map (\r
562d2849 2584 HcDev->PciIo,\r
2585 EfiPciIoOperationBusMasterWrite,\r
2586 PtrDataSource,\r
2587 &DataLen,\r
2588 &TempPtr,\r
2589 &Mapping\r
2590 );\r
878ddf1f 2591 if (EFI_ERROR (Status)) {\r
2592 return Status;\r
2593 }\r
2594\r
2595 Ptr = (UINT8 *) ((UINTN) TempPtr);\r
2596 break;\r
2597\r
2598 case EfiUsbDataOut:\r
2599 PktID = OUTPUT_PACKET_ID;\r
2600 PtrDataSource = Data;\r
2601 DataLen = *DataLength;\r
2602\r
2603 //\r
2604 // BusMasterRead means cpu write\r
2605 //\r
2606 Status = HcDev->PciIo->Map (\r
562d2849 2607 HcDev->PciIo,\r
2608 EfiPciIoOperationBusMasterRead,\r
2609 PtrDataSource,\r
2610 &DataLen,\r
2611 &TempPtr,\r
2612 &Mapping\r
2613 );\r
878ddf1f 2614 if (EFI_ERROR (Status)) {\r
2615 return Status;\r
2616 }\r
2617\r
2618 Ptr = (UINT8 *) ((UINTN) TempPtr);\r
2619 break;\r
2620\r
2621 default:\r
2622 return EFI_INVALID_PARAMETER;\r
2623 }\r
2624 \r
2625 //\r
2626 // create QH structure and init\r
2627 //\r
2628 Status = CreateQH (HcDev, &PtrQH);\r
2629 if (EFI_ERROR (Status)) {\r
2630 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2631 return Status;\r
2632 }\r
2633 \r
2634 //\r
2635 // i is used to calculate the total number of TDs.\r
2636 //\r
2637 Index = 0;\r
2638\r
2639 IsFirstTD = TRUE;\r
2640 while (DataLen > 0) {\r
2641 \r
2642 //\r
2643 // create TD structures and link together\r
2644 //\r
2645 \r
2646 PktSize = (UINT8) DataLen;\r
2647 if (DataLen > MaximumPacketLength) {\r
2648 PktSize = MaximumPacketLength;\r
2649 }\r
2650\r
2651 Status = GenDataTD (\r
562d2849 2652 HcDev,\r
2653 DeviceAddress,\r
2654 EndPointAddress,\r
2655 Ptr,\r
2656 PktSize,\r
2657 PktID,\r
2658 *DataToggle,\r
2659 FALSE,\r
2660 &PtrTD\r
2661 );\r
878ddf1f 2662\r
2663 if (EFI_ERROR (Status)) {\r
2664 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2665 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
2666 DeleteQueuedTDs (HcDev, PtrFirstTD);\r
2667 return Status;\r
2668 }\r
2669 \r
2670 //\r
2671 // Enable short packet detection.\r
2672 // (default action is disabling short packet detection)\r
2673 //\r
2674 if (ShortPacketEnable) {\r
2675 EnableorDisableTDShortPacket (PtrTD, TRUE);\r
2676 }\r
2677\r
2678 if (IsFirstTD) {\r
2679 PtrFirstTD = PtrTD;\r
2680 PtrFirstTD->ptrNextTD = NULL;\r
2681 IsFirstTD = FALSE;\r
2682 } else {\r
2683 //\r
2684 // Link two TDs in vertical depth\r
2685 //\r
2686 LinkTDToTD (PtrPreTD, PtrTD);\r
2687 }\r
2688\r
2689 Index++;\r
2690\r
2691 PtrPreTD = PtrTD;\r
2692\r
2693 *DataToggle ^= 1;\r
2694 Ptr += PktSize;\r
2695 DataLen -= PktSize;\r
2696 }\r
2697 \r
2698 //\r
2699 // link TD structures to QH structure\r
2700 //\r
2701 LinkTDToQH (PtrQH, PtrFirstTD);\r
2702\r
2703 //\r
2704 // calculate how many entries are linked to the specified bulk transfer QH-TDs\r
2705 // the below values are referred to the USB spec revision1.1.\r
2706 //\r
2707 switch (MaximumPacketLength) {\r
2708 case 8:\r
2709 LinkTimes = Index / 71 + 1;\r
2710 break;\r
2711\r
2712 case 16:\r
2713 LinkTimes = Index / 51 + 1;\r
2714 break;\r
2715\r
2716 case 32:\r
2717 LinkTimes = Index / 33 + 1;\r
2718 break;\r
2719\r
2720 case 64:\r
2721 LinkTimes = Index / 19 + 1;\r
2722 break;\r
2723 }\r
2724\r
2725 LinkTimes += 500;\r
2726\r
2727 //\r
2728 // put QH-TDs into Frame list\r
2729 //\r
2730 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
2731 SavedFrameListIndex = LoadFrameListIndex;\r
2732\r
2733 for (Index = 0; Index <= LinkTimes; Index++) {\r
2734 \r
2735 //\r
2736 // put the QH-TD directly or indirectly into the proper place\r
2737 // in the Frame List\r
2738 //\r
2739 LinkQHToFrameList (HcDev->FrameListEntry, LoadFrameListIndex, PtrQH);\r
2740\r
2741 LoadFrameListIndex += 1;\r
2742 LoadFrameListIndex &= 0x3FF;\r
2743 }\r
2744\r
2745 LoadFrameListIndex = SavedFrameListIndex;\r
2746\r
2747 //\r
2748 // Execute QH-TD and get result\r
2749 //\r
2750 //\r
2751 // detail status is put into the Result field in the pIRP\r
2752 // the Data Toggle value is also re-updated to the value\r
2753 // of the last successful TD\r
2754 //\r
2755 Status = ExecBulkorSyncInterruptTransfer (\r
562d2849 2756 HcDev,\r
2757 PtrFirstTD,\r
2758 LoadFrameListIndex,\r
2759 DataLength,\r
2760 DataToggle,\r
2761 TimeOut,\r
2762 TransferResult\r
2763 );\r
878ddf1f 2764\r
2765 //\r
2766 // Delete Bulk transfer QH-TD structure\r
2767 // and maitain the pointers in the Frame List\r
2768 // and other pointers in related QH structure\r
2769 //\r
2770 // TRUE means must search other framelistindex\r
2771 //\r
2772 for (Index = 0; Index <= LinkTimes; Index++) {\r
2773 DelLinkSingleQH (\r
2774 HcDev,\r
2775 PtrQH,\r
2776 LoadFrameListIndex,\r
2777 FALSE,\r
2778 FALSE\r
2779 );\r
2780 LoadFrameListIndex += 1;\r
2781 LoadFrameListIndex &= 0x3FF;\r
2782 }\r
2783\r
2784 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
2785\r
2786 DeleteQueuedTDs (HcDev, PtrFirstTD);\r
2787\r
2788 if (Mapping != NULL) {\r
2789 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
2790 }\r
2791 \r
2792 //\r
2793 // if has errors that cause host controller halt,\r
2794 // then return EFI_DEVICE_ERROR directly.\r
2795 //\r
2796 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
2797\r
2798 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2799 *TransferResult |= EFI_USB_ERR_SYSTEM;\r
2800 return EFI_DEVICE_ERROR;\r
2801 }\r
2802\r
2803 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2804\r
2805 HcDev->PciIo->Flush (HcDev->PciIo);\r
2806\r
2807 return Status;\r
2808}\r
2809\r
2810EFI_STATUS\r
2811EFIAPI\r
2812UHCIAsyncInterruptTransfer (\r
2813 IN EFI_USB_HC_PROTOCOL * This,\r
2814 IN UINT8 DeviceAddress,\r
2815 IN UINT8 EndPointAddress,\r
2816 IN BOOLEAN IsSlowDevice,\r
562d2849 2817 IN UINT8 MaximumPacketLength,\r
878ddf1f 2818 IN BOOLEAN IsNewTransfer,\r
2819 IN OUT UINT8 *DataToggle,\r
2820 IN UINTN PollingInterval, OPTIONAL\r
2821 IN UINTN DataLength, OPTIONAL\r
2822 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, OPTIONAL\r
2823 IN VOID *Context OPTIONAL\r
2824 )\r
2825/*++\r
2826 \r
2827 Routine Description:\r
2828 Submits an asynchronous interrupt transfer to an \r
2829 interrupt endpoint of a USB device.\r
2830 \r
2831 Arguments:\r
2832 \r
2833 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
2834 \r
2835 DeviceAddress Represents the address of the target device on the USB,\r
2836 which is assigned during USB enumeration.\r
2837 \r
2838 EndPointAddress The combination of an endpoint number and an endpoint \r
2839 direction of the target USB device. Each endpoint address \r
2840 supports data transfer in one direction except the \r
2841 control endpoint (whose default endpoint address is 0). \r
2842 It is the caller's responsibility to make sure that \r
2843 the EndPointAddress represents an interrupt endpoint.\r
2844 \r
2845 IsSlowDevice Indicates whether the target device is slow device \r
2846 or full-speed device.\r
2847 \r
562d2849 2848 MaximumPacketLength Indicates the maximum packet size the target endpoint\r
878ddf1f 2849 is capable of sending or receiving.\r
2850 \r
2851 IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between\r
2852 the host and the target interrupt endpoint. \r
2853 If FALSE, the specified asynchronous interrupt pipe \r
2854 is canceled.\r
2855 \r
2856 DataToggle A pointer to the data toggle value. On input, it is valid \r
2857 when IsNewTransfer is TRUE, and it indicates the initial \r
2858 data toggle value the asynchronous interrupt transfer \r
2859 should adopt. \r
2860 On output, it is valid when IsNewTransfer is FALSE, \r
2861 and it is updated to indicate the data toggle value of \r
2862 the subsequent asynchronous interrupt transfer.\r
2863 \r
2864 PollingInterval Indicates the interval, in milliseconds, that the \r
2865 asynchronous interrupt transfer is polled. \r
2866 This parameter is required when IsNewTransfer is TRUE.\r
2867 \r
2868 DataLength Indicates the length of data to be received at the \r
2869 rate specified by PollingInterval from the target \r
2870 asynchronous interrupt endpoint. This parameter \r
2871 is only required when IsNewTransfer is TRUE.\r
2872 \r
2873 CallBackFunction The Callback function.This function is called at the \r
2874 rate specified by PollingInterval.This parameter is \r
2875 only required when IsNewTransfer is TRUE.\r
2876 \r
2877 Context The context that is passed to the CallBackFunction.\r
2878 This is an optional parameter and may be NULL.\r
2879 \r
2880 Returns:\r
2881 EFI_SUCCESS \r
2882 The asynchronous interrupt transfer request has been successfully \r
2883 submitted or canceled.\r
2884 EFI_INVALID_PARAMETER \r
2885 Some parameters are invalid.\r
2886 EFI_OUT_OF_RESOURCES \r
2887 The request could not be completed due to a lack of resources. \r
2888 EFI_DEVICE_ERROR\r
2889 Can't read register\r
2890--*/\r
2891{\r
2892 USB_HC_DEV *HcDev;\r
2893 UINT32 StatusReg;\r
2894 UINT32 FrameNumReg;\r
2895 UINTN DataLen;\r
2896 QH_STRUCT *ptrFirstQH;\r
2897 QH_STRUCT *PtrQH;\r
2898 QH_STRUCT *ptrPreQH;\r
2899 TD_STRUCT *PtrFirstTD;\r
2900 TD_STRUCT *PtrTD;\r
2901 TD_STRUCT *PtrPreTD;\r
2902 UINT16 LoadFrameListIndex;\r
2903 UINT16 Index;\r
2904 UINT8 PktID;\r
2905 UINT8 *Ptr;\r
2906 UINT8 *MappedPtr;\r
2907 BOOLEAN IsFirstTD;\r
2908 BOOLEAN IsFirstQH;\r
2909 EFI_STATUS Status;\r
2910 BOOLEAN ShortPacketEnable;\r
2911 UINT8 CurrentDataToggle;\r
2912 EFI_PHYSICAL_ADDRESS TempPtr;\r
2913 VOID *Mapping;\r
2914 UINT8 PktSize;\r
2915 QH_STRUCT *TempQH;\r
2916 EFI_TPL OldTpl;\r
2917\r
2918 HcDev = USB_HC_DEV_FROM_THIS (This);\r
2919 StatusReg = (UINT32) (USBSTS);\r
2920 FrameNumReg = (UINT32) (USBFRNUM);\r
2921 Mapping = NULL;\r
2922 ShortPacketEnable = FALSE;\r
2923\r
2924 PktID = INPUT_PACKET_ID;\r
2925 PtrTD = NULL;\r
2926 PtrFirstTD = NULL;\r
2927 PtrPreTD = NULL;\r
2928 Ptr = NULL;\r
2929 PtrQH = NULL;\r
2930 ptrPreQH = NULL;\r
2931 ptrFirstQH = NULL;\r
2932\r
2933 if ((EndPointAddress & 0x80) == 0) {\r
2934 return EFI_INVALID_PARAMETER;\r
2935 }\r
2936 \r
2937 //\r
2938 // delete Async interrupt transfer request\r
2939 //\r
2940 if (!IsNewTransfer) {\r
2941\r
2942 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);\r
2943\r
2944 Status = DeleteAsyncINTQHTDs (\r
562d2849 2945 HcDev,\r
2946 DeviceAddress,\r
2947 EndPointAddress,\r
2948 DataToggle\r
2949 );\r
878ddf1f 2950\r
2951 gBS->RestoreTPL (OldTpl);\r
2952\r
2953 return Status;\r
2954 }\r
2955 //\r
2956 // if has errors that cause host controller halt,\r
2957 // then return EFI_DEVICE_ERROR directly.\r
2958 //\r
2959 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
2960\r
2961 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2962 return EFI_DEVICE_ERROR;\r
2963 }\r
2964\r
2965 ClearStatusReg (HcDev->PciIo, StatusReg);\r
2966\r
2967 //\r
2968 // submit Async interrupt transfer request\r
2969 //\r
2970 if (PollingInterval < 1 || PollingInterval > 255) {\r
2971 return EFI_INVALID_PARAMETER;\r
2972 }\r
2973\r
2974 if (DataLength == 0) {\r
2975 return EFI_INVALID_PARAMETER;\r
2976 }\r
2977\r
2978 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
2979 return EFI_INVALID_PARAMETER;\r
2980 }\r
2981\r
2982 ShortPacketEnable = TRUE;\r
2983 PktID = INPUT_PACKET_ID;\r
2984 DataLen = DataLength;\r
2985 Ptr = AllocatePool (DataLen);\r
2986 if (Ptr == NULL) {\r
2987 return EFI_OUT_OF_RESOURCES;\r
2988 }\r
2989\r
2990 //\r
2991 // BusMasterWrite means cpu read\r
2992 //\r
2993 Status = HcDev->PciIo->Map (\r
562d2849 2994 HcDev->PciIo,\r
2995 EfiPciIoOperationBusMasterWrite,\r
2996 Ptr,\r
2997 &DataLen,\r
2998 &TempPtr,\r
2999 &Mapping\r
3000 );\r
878ddf1f 3001 if (EFI_ERROR (Status)) {\r
3002 gBS->FreePool (Ptr);\r
3003 return Status;\r
3004 }\r
3005\r
3006 MappedPtr = (UINT8 *) ((UINTN) TempPtr);\r
3007\r
3008 CurrentDataToggle = *DataToggle;\r
3009\r
3010 IsFirstTD = TRUE;\r
3011\r
3012 while (DataLen > 0) {\r
3013 //\r
3014 // create TD structures and link together\r
3015 //\r
3016 \r
3017 PktSize = (UINT8) DataLen;\r
562d2849 3018 if (DataLen > MaximumPacketLength) {\r
3019 PktSize = MaximumPacketLength;\r
878ddf1f 3020 }\r
3021\r
3022 Status = GenDataTD (\r
562d2849 3023 HcDev,\r
3024 DeviceAddress,\r
3025 EndPointAddress,\r
3026 MappedPtr,\r
3027 PktSize,\r
3028 PktID,\r
3029 CurrentDataToggle,\r
3030 IsSlowDevice,\r
3031 &PtrTD\r
3032 );\r
3033 if (EFI_ERROR (Status)) {\r
3034 gBS->FreePool (Ptr);\r
878ddf1f 3035 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
3036 DeleteQueuedTDs (HcDev, PtrFirstTD);\r
3037 return Status;\r
3038 }\r
3039 //\r
3040 // Enable short packet detection.\r
3041 //\r
3042 if (ShortPacketEnable) {\r
3043 EnableorDisableTDShortPacket (PtrTD, TRUE);\r
3044 }\r
3045\r
3046 if (IsFirstTD) {\r
3047 PtrFirstTD = PtrTD;\r
3048 PtrFirstTD->ptrNextTD = NULL;\r
3049 IsFirstTD = FALSE;\r
3050 } else {\r
3051 //\r
3052 // Link two TDs in vertical depth\r
3053 //\r
3054 LinkTDToTD (PtrPreTD, PtrTD);\r
3055 }\r
3056\r
3057 PtrPreTD = PtrTD;\r
3058\r
3059 CurrentDataToggle ^= 1;\r
3060 MappedPtr += PktSize;\r
3061 DataLen -= PktSize;\r
3062 }\r
3063 \r
3064 //\r
3065 // roll one value back\r
3066 //\r
3067 CurrentDataToggle ^= 1;\r
3068\r
3069 //\r
3070 // create a list of QH structures and init,\r
3071 // link TDs to all the QHs, and link all the QHs together using internal\r
3072 // defined pointer of the QH_STRUCT.\r
3073 //\r
3074 IsFirstQH = TRUE;\r
3075 ptrPreQH = NULL;\r
3076 for (Index = 0; Index < 1024;) {\r
3077\r
3078 Status = CreateQH (HcDev, &PtrQH);\r
3079 if (EFI_ERROR (Status)) {\r
3080 gBS->FreePool (Ptr);\r
3081 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
3082 DeleteQueuedTDs (HcDev, PtrFirstTD);\r
3083 PtrQH = ptrFirstQH;\r
3084 while (PtrQH) {\r
3085 TempQH = PtrQH;\r
3086 PtrQH = TempQH->ptrNextIntQH;\r
3087 UhciFreePool (HcDev, (UINT8 *) TempQH, sizeof (QH_STRUCT));\r
3088 }\r
3089\r
3090 return Status;\r
3091 }\r
3092 \r
3093 //\r
3094 // link TD structures to QH structure\r
3095 //\r
3096 LinkTDToQH (PtrQH, PtrFirstTD);\r
3097\r
3098 if (IsFirstQH) {\r
3099 ptrFirstQH = PtrQH;\r
3100 ptrFirstQH->ptrNextIntQH = NULL;\r
3101 IsFirstQH = FALSE;\r
3102 } else {\r
3103 //\r
3104 // link neighbor QH structures together\r
3105 //\r
3106 ptrPreQH->ptrNextIntQH = PtrQH;\r
3107 }\r
3108\r
3109 ptrPreQH = PtrQH;\r
3110\r
3111 Index = (UINT16) (PollingInterval + Index);\r
3112 }\r
3113 //\r
3114 // last QH in QH list should set its next QH pointer to NULL.\r
3115 //\r
3116 PtrQH->ptrNextIntQH = NULL;\r
3117\r
3118 //\r
3119 // Save QH-TD structures in Interrupt transfer list,\r
3120 // for monitor interrupt transfer execution routine use.\r
3121 //\r
3122 InsertQHTDToINTList (\r
3123 HcDev,\r
3124 ptrFirstQH,\r
3125 PtrFirstTD,\r
3126 DeviceAddress,\r
3127 EndPointAddress,\r
3128 CurrentDataToggle,\r
3129 DataLength,\r
3130 PollingInterval,\r
3131 Mapping,\r
3132 Ptr,\r
3133 CallBackFunction,\r
3134 Context\r
3135 );\r
3136\r
3137 //\r
3138 // put QHs-TDs into Frame list\r
3139 //\r
3140 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
3141\r
3142 PtrQH = ptrFirstQH;\r
3143\r
3144 for (Index = LoadFrameListIndex; Index < (1024 + LoadFrameListIndex);) {\r
3145 \r
3146 //\r
3147 // put the QH-TD directly or indirectly into the proper place\r
3148 // in the Frame List\r
3149 //\r
3150 LinkQHToFrameList (HcDev->FrameListEntry, (UINT16) (Index & 0x3FF), PtrQH);\r
3151\r
3152 Index = (UINT16) (PollingInterval + Index);\r
3153\r
3154 PtrQH = PtrQH->ptrNextIntQH;\r
3155 }\r
3156\r
3157 HcDev->PciIo->Flush (HcDev->PciIo);\r
3158\r
3159 return EFI_SUCCESS;\r
3160}\r
3161\r
3162EFI_STATUS\r
3163EFIAPI\r
3164UHCISyncInterruptTransfer (\r
3165 IN EFI_USB_HC_PROTOCOL *This,\r
3166 IN UINT8 DeviceAddress,\r
3167 IN UINT8 EndPointAddress,\r
3168 IN BOOLEAN IsSlowDevice,\r
3169 IN UINT8 MaximumPacketLength,\r
3170 IN OUT VOID *Data,\r
3171 IN OUT UINTN *DataLength,\r
3172 IN OUT UINT8 *DataToggle,\r
3173 IN UINTN TimeOut,\r
3174 OUT UINT32 *TransferResult\r
3175 )\r
3176/*++\r
3177 \r
3178 Routine Description:\r
3179 Submits synchronous interrupt transfer to an interrupt endpoint \r
3180 of a USB device.\r
3181 \r
3182 Arguments:\r
3183 \r
3184 This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
3185 \r
3186 DeviceAddress Represents the address of the target device on the USB, \r
3187 which is assigned during USB enumeration.\r
3188 \r
3189 EndPointAddress The combination of an endpoint number and an endpoint \r
3190 direction of the target USB device. Each endpoint \r
3191 address supports data transfer in one direction \r
3192 except the control endpoint (whose default \r
3193 endpoint address is 0). It is the caller's responsibility\r
3194 to make sure that the EndPointAddress represents \r
3195 an interrupt endpoint. \r
3196 \r
3197 IsSlowDevice Indicates whether the target device is slow device \r
3198 or full-speed device.\r
3199 \r
3200 MaximumPacketLength Indicates the maximum packet size the target endpoint \r
3201 is capable of sending or receiving.\r
3202 \r
3203 Data A pointer to the buffer of data that will be transmitted \r
3204 to USB device or received from USB device.\r
3205 \r
3206 DataLength On input, the size, in bytes, of the data buffer specified \r
3207 by Data. On output, the number of bytes transferred.\r
3208 \r
3209 DataToggle A pointer to the data toggle value. On input, it indicates\r
3210 the initial data toggle value the synchronous interrupt \r
3211 transfer should adopt; \r
3212 on output, it is updated to indicate the data toggle value \r
3213 of the subsequent synchronous interrupt transfer. \r
3214 \r
3215 TimeOut Indicates the maximum time, in microseconds, which the \r
3216 transfer is allowed to complete.\r
3217 \r
3218 TransferResult A pointer to the detailed result information from \r
3219 the synchronous interrupt transfer. \r
3220\r
3221 Returns:\r
3222 EFI_SUCCESS \r
3223 The synchronous interrupt transfer was completed successfully.\r
3224 EFI_OUT_OF_RESOURCES \r
3225 The synchronous interrupt transfer could not be submitted due \r
3226 to lack of resource.\r
3227 EFI_INVALID_PARAMETER \r
3228 Some parameters are invalid.\r
3229 EFI_TIMEOUT \r
3230 The synchronous interrupt transfer failed due to timeout.\r
3231 EFI_DEVICE_ERROR \r
3232 The synchronous interrupt transfer failed due to host controller \r
3233 or device error. Caller should check TranferResult for detailed \r
3234 error information. \r
3235--*/\r
3236{\r
3237 USB_HC_DEV *HcDev;\r
3238 UINT32 StatusReg;\r
3239 UINT32 FrameNumReg;\r
3240 UINTN DataLen;\r
3241 QH_STRUCT *PtrQH;\r
3242 TD_STRUCT *PtrFirstTD;\r
3243 TD_STRUCT *PtrTD;\r
3244 TD_STRUCT *PtrPreTD;\r
3245 UINT16 LoadFrameListIndex;\r
3246 UINT16 SavedFrameListIndex;\r
3247 UINT32 Index;\r
3248 UINT32 LinkTimes;\r
3249 UINT8 PktID;\r
3250 UINT8 *PtrDataSource;\r
3251 UINT8 *Ptr;\r
3252 BOOLEAN IsFirstTD;\r
3253 EFI_STATUS Status;\r
3254 BOOLEAN ShortPacketEnable;\r
3255 EFI_PHYSICAL_ADDRESS TempPtr;\r
3256 VOID *Mapping;\r
3257 UINT8 PktSize;\r
3258\r
3259 HcDev = USB_HC_DEV_FROM_THIS (This);\r
3260 StatusReg = (UINT32) (USBSTS);\r
3261 FrameNumReg = (UINT32) (USBFRNUM);\r
3262 ShortPacketEnable = FALSE;\r
3263 Mapping = NULL;\r
3264 PktID = INPUT_PACKET_ID;\r
3265 PtrTD = NULL;\r
3266 PtrFirstTD = NULL;\r
3267 PtrPreTD = NULL;\r
3268 DataLen = 0;\r
3269 Ptr = NULL;\r
3270 Index = 0;\r
3271 LinkTimes = 0;\r
3272\r
3273 //\r
3274 // Parameters Checking\r
3275 //\r
3276 \r
3277 if ((DataLength == NULL) ||\r
3278 (Data == NULL) ||\r
3279 (TransferResult == NULL)) {\r
3280 return EFI_INVALID_PARAMETER;\r
3281 }\r
3282 \r
3283 //\r
3284 // if has errors that cause host controller halt,\r
3285 // then return EFI_DEVICE_ERROR directly.\r
3286 //\r
3287 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
3288\r
3289 ClearStatusReg (HcDev->PciIo, StatusReg);\r
3290 *TransferResult = EFI_USB_ERR_SYSTEM;\r
3291 return EFI_DEVICE_ERROR;\r
3292 }\r
3293\r
3294 if ((EndPointAddress & 0x80) == 0) {\r
3295 return EFI_INVALID_PARAMETER;\r
3296 }\r
3297\r
3298 if (*DataLength == 0) {\r
3299 return EFI_INVALID_PARAMETER;\r
3300 }\r
3301\r
3302 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
3303 return EFI_INVALID_PARAMETER;\r
3304 }\r
3305\r
3306 if (MaximumPacketLength > 64) {\r
3307 return EFI_INVALID_PARAMETER;\r
3308 }\r
3309\r
3310 if (IsSlowDevice && (MaximumPacketLength > 8)) {\r
3311 return EFI_INVALID_PARAMETER;\r
3312 }\r
3313\r
562d2849 3314 if (TransferResult == NULL) {\r
3315 return EFI_INVALID_PARAMETER;\r
3316 }\r
3317\r
878ddf1f 3318 ClearStatusReg (HcDev->PciIo, StatusReg);\r
3319\r
3320 //\r
3321 // submit Sync interrupt transfer request\r
3322 //\r
3323 ShortPacketEnable = TRUE;\r
3324 PktID = INPUT_PACKET_ID;\r
3325 DataLen = *DataLength;\r
3326 PtrDataSource = Data;\r
3327\r
3328 //\r
3329 // create QH structure and init\r
3330 //\r
3331 Status = CreateQH (HcDev, &PtrQH);\r
3332 if (EFI_ERROR (Status)) {\r
3333 return Status;\r
3334 }\r
3335 \r
3336 //\r
3337 // BusMasterWrite means cpu read\r
3338 //\r
3339 Status = HcDev->PciIo->Map (\r
3340 HcDev->PciIo,\r
3341 EfiPciIoOperationBusMasterWrite,\r
3342 PtrDataSource,\r
3343 &DataLen,\r
3344 &TempPtr,\r
3345 &Mapping\r
3346 );\r
3347 if (EFI_ERROR (Status)) {\r
3348 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
3349 return Status;\r
3350 }\r
3351\r