]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.c
Allocate ACPImemoryNVS type memory to save mailbox and debug port handle buffer since...
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugCommunicationLibUsb / DebugCommunicationLibUsb.c
CommitLineData
18b144ea 1/** @file\r
2 Debug Port Library implementation based on usb debug port.\r
3\r
b422b62c 4 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
18b144ea 5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php.\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <Base.h>\r
16#include <IndustryStandard/Pci.h>\r
17#include <IndustryStandard/Usb.h>\r
18#include <Library/IoLib.h>\r
19#include <Library/PciLib.h>\r
20#include <Library/PcdLib.h>\r
21#include <Library/TimerLib.h>\r
22#include <Library/DebugCommunicationLib.h>\r
23#include <Library/BaseMemoryLib.h>\r
24#include <Library/BaseLib.h>\r
e2104834 25#include <Library/DebugLib.h>\r
18b144ea 26\r
27#define SETUP_PID 0x2D\r
28#define INPUT_PID 0x69\r
29#define OUTPUT_PID 0xE1\r
30#define ERROR_PID 0x55\r
31#define DATA0_PID 0xC3\r
32#define DATA1_PID 0x4B\r
33#define DATA2_PID 0x87\r
34#define MDATA_PID 0x0F\r
35#define ACK_PID 0xD2\r
36#define NAK_PID 0x5A\r
37#define STALL_PID 0x1E\r
38#define NYET_PID 0x96\r
39\r
40#define PCI_CAPABILITY_ID_DEBUG_PORT 0x0A\r
41#define USB_DEBUG_PORT_MAX_PACKET_SIZE 0x08\r
42\r
43#define USB_DEBUG_PORT_IN_USE BIT10\r
44#define USB_DEBUG_PORT_ENABLE BIT28\r
45#define USB_DEBUG_PORT_OWNER BIT30\r
46\r
47#define USB_PORT_LINE_STATUS_LS 0x400\r
48#define USB_PORT_LINE_STATUS_MASK 0xC00\r
49\r
50//\r
51// Usb debug device descriptor, which is defined at\r
52// USB2 Debug Device Specification.\r
53//\r
54typedef struct _USB_DEBUG_PORT_DESCRIPTOR {\r
55 UINT8 Length;\r
56 UINT8 DescriptorType;\r
57 UINT8 DebugInEndpoint;\r
58 UINT8 DebugOutEndpoint;\r
59}USB_DEBUG_PORT_DESCRIPTOR;\r
60\r
61USB_DEVICE_REQUEST mGetDebugDescriptor = {\r
62 0x80,\r
63 USB_REQ_GET_DESCRIPTOR,\r
64 (UINT16)(0x0A << 8),\r
65 0x0000,\r
66 sizeof(USB_DEBUG_PORT_DESCRIPTOR)\r
67 };\r
68\r
69USB_DEVICE_REQUEST mSetDebugFeature = {\r
70 0x0,\r
71 USB_REQ_SET_FEATURE,\r
72 (UINT16)(0x06),\r
73 0x0000,\r
74 0x0\r
75 };\r
76\r
77USB_DEVICE_REQUEST mSetDebugAddress = {\r
78 0x0,\r
79 USB_REQ_SET_ADDRESS,\r
80 (UINT16)(0x7F),\r
81 0x0000,\r
82 0x0\r
83 };\r
84\r
85//\r
86// Usb debug port register file, which is defined at\r
87// EHCI Specification.\r
88//\r
89typedef struct _USB_DEBUG_PORT_REGISTER {\r
90 UINT32 ControlStatus;\r
91 UINT8 TokenPid;\r
92 UINT8 SendPid;\r
93 UINT8 ReceivedPid;\r
94 UINT8 Reserved1;\r
95 UINT8 DataBuffer[8];\r
96 UINT8 UsbEndPoint;\r
97 UINT8 UsbAddress;\r
98 UINT8 Reserved2;\r
99 UINT8 Reserved3;\r
100}USB_DEBUG_PORT_REGISTER;\r
101\r
93c0bdec 102//\r
103// The state machine of usb debug port\r
104//\r
105#define USBDBG_NO_DEV 0 // No device present at debug port\r
106#define USBDBG_NO_DBG_CAB 1 // The device attached is not usb debug cable\r
107#define USBDBG_DBG_CAB 2 // The device attached is usb debug cable\r
108#define USBDBG_INIT_DONE 4 // The usb debug cable device is initialized\r
109#define USBDBG_RESET 8 // The system is reset\r
110\r
18b144ea 111#pragma pack(1)\r
112//\r
113// The internal data structure of DEBUG_PORT_HANDLE, which stores some\r
114// important datum which are used across various phases.\r
115//\r
116typedef struct _USB_DEBUG_PORT_HANDLE{\r
117 //\r
118 // The usb debug port memory BAR number in EHCI configuration space.\r
119 //\r
120 UINT8 DebugPortBarNumber;\r
93c0bdec 121 UINT8 Initialized;\r
18b144ea 122 //\r
123 // The offset of usb debug port registers in EHCI memory range.\r
124 //\r
125 UINT16 DebugPortOffset;\r
126 //\r
127 // The usb debug port memory BAR address.\r
128 //\r
93c0bdec 129 UINT32 UsbDebugPortMemoryBase;\r
18b144ea 130 //\r
131 // The EHCI memory BAR address.\r
132 //\r
93c0bdec 133 UINT32 EhciMemoryBase;\r
18b144ea 134 //\r
135 // The Bulk In endpoint toggle bit.\r
136 //\r
137 UINT8 BulkInToggle;\r
138 //\r
139 // The Bulk Out endpoint toggle bit.\r
140 //\r
141 UINT8 BulkOutToggle;\r
142 //\r
143 // The available data length in the following data buffer.\r
144 //\r
145 UINT8 DataCount;\r
146 //\r
147 // The data buffer. Maximum length is 8 bytes.\r
148 //\r
149 UINT8 Data[8];\r
b422b62c 150 //\r
151 // Timter settings\r
152 //\r
153 UINT64 TimerFrequency;\r
154 UINT64 TimerCycle;\r
155 BOOLEAN TimerCountDown;\r
18b144ea 156} USB_DEBUG_PORT_HANDLE;\r
157#pragma pack()\r
158\r
159//\r
160// The global variable which can be used after memory is ready.\r
161//\r
162USB_DEBUG_PORT_HANDLE mUsbDebugPortHandle;\r
163\r
b422b62c 164/**\r
165 Check if the timer is timeout.\r
166 \r
167 @param[in] UsbDebugPortHandle Pointer to USB Debug port handle\r
168 @param[in] Timer The start timer from the begin.\r
169 @param[in] TimeoutTicker Ticker number need time out.\r
170\r
171 @return TRUE Timer time out occurs.\r
172 @retval FALSE Timer does not time out.\r
173\r
174**/\r
175BOOLEAN\r
176IsTimerTimeout (\r
177 IN USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle,\r
178 IN UINT64 Timer,\r
179 IN UINT64 TimeoutTicker\r
180 )\r
181{\r
182 UINT64 CurrentTimer;\r
183 UINT64 Delta;\r
184\r
185 CurrentTimer = GetPerformanceCounter ();\r
186\r
187 if (UsbDebugPortHandle->TimerCountDown) {\r
188 //\r
189 // The timer counter counts down. Check for roll over condition.\r
190 //\r
191 if (CurrentTimer < Timer) {\r
192 Delta = Timer - CurrentTimer;\r
193 } else {\r
194 //\r
195 // Handle one roll-over. \r
196 //\r
197 Delta = UsbDebugPortHandle->TimerCycle - (CurrentTimer - Timer);\r
198 }\r
199 } else {\r
200 //\r
201 // The timer counter counts up. Check for roll over condition.\r
202 //\r
203 if (CurrentTimer > Timer) {\r
204 Delta = CurrentTimer - Timer;\r
205 } else {\r
206 //\r
207 // Handle one roll-over. \r
208 //\r
209 Delta = UsbDebugPortHandle->TimerCycle - (Timer - CurrentTimer);\r
210 }\r
211 }\r
212 \r
213 return (BOOLEAN) (Delta >= TimeoutTicker);\r
214}\r
215\r
18b144ea 216/**\r
217 Calculate the usb debug port bar address.\r
218\r
219 @param DebugPortOffset Get usb debug port offset in the usb debug port memory space.\r
220 @param DebugPortBarNumbar Get the bar number at which usb debug port is located.\r
221\r
222 @retval RETURN_UNSUPPORTED The usb host controller does not supported usb debug port capability.\r
223 @retval RETURN_SUCCESS Get bar and offset successfully.\r
224\r
225**/\r
226RETURN_STATUS\r
227EFIAPI\r
228CalculateUsbDebugPortBar (\r
229 OUT UINT16 *DebugPortOffset,\r
230 OUT UINT8 *DebugPortBarNumbar\r
231 )\r
232{\r
233 UINT16 PciStatus;\r
f98c2685 234 UINT16 VendorId;\r
235 UINT16 DeviceId;\r
236 UINT8 ProgInterface;\r
237 UINT8 SubClassCode;\r
238 UINT8 BaseCode;\r
18b144ea 239 UINT8 CapabilityPtr;\r
240 UINT8 CapabilityId;\r
241\r
f98c2685 242 VendorId = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_VENDOR_ID_OFFSET);\r
243 DeviceId = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_DEVICE_ID_OFFSET);\r
244 \r
245 if ((VendorId == 0xFFFF) || (DeviceId == 0xFFFF)) {\r
246 return RETURN_UNSUPPORTED;\r
247 }\r
248\r
249 ProgInterface = PciRead8 (PcdGet32(PcdUsbEhciPciAddress) + PCI_CLASSCODE_OFFSET);\r
250 SubClassCode = PciRead8 (PcdGet32(PcdUsbEhciPciAddress) + PCI_CLASSCODE_OFFSET + 1);\r
251 BaseCode = PciRead8 (PcdGet32(PcdUsbEhciPciAddress) + PCI_CLASSCODE_OFFSET + 2);\r
252 \r
253 if ((ProgInterface != PCI_IF_EHCI) || (SubClassCode != PCI_CLASS_SERIAL_USB) || (BaseCode != PCI_CLASS_SERIAL)) {\r
254 return RETURN_UNSUPPORTED;\r
255 }\r
256\r
18b144ea 257 //\r
258 // Enable Ehci Host Controller MMIO Space.\r
259 //\r
260 PciStatus = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_PRIMARY_STATUS_OFFSET);\r
261\r
262 if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {\r
263 //\r
264 // The Pci Device Doesn't Support Capability Pointer.\r
265 //\r
266 return RETURN_UNSUPPORTED;\r
267 }\r
268\r
269 //\r
270 // Get Pointer To Capability List\r
271 //\r
272 CapabilityPtr = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + PCI_CAPBILITY_POINTER_OFFSET);\r
273\r
274 //\r
275 // Find Capability ID 0xA, Which Is For Debug Port\r
276 //\r
277 while (CapabilityPtr != 0) {\r
278 CapabilityId = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr);\r
279 if (CapabilityId == PCI_CAPABILITY_ID_DEBUG_PORT) {\r
280 break;\r
281 }\r
282 CapabilityPtr = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 1);\r
283 }\r
284\r
285 //\r
286 // No Debug Port Capability Found\r
287 //\r
288 if (CapabilityPtr == 0) {\r
289 return RETURN_UNSUPPORTED;\r
290 }\r
291\r
292 //\r
293 // Get The Base Address Of Debug Port Register In Debug Port Capability Register\r
294 //\r
295 *DebugPortOffset = (UINT16)(PciRead16(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 2) & 0x1FFF);\r
296 *DebugPortBarNumbar = (UINT8)((PciRead16(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 2) >> 13) - 1);\r
297\r
298 return RETURN_SUCCESS;\r
299}\r
300\r
301/**\r
302 Do a usb IN transaction by usb debug port.\r
303\r
304 @param DebugPortRegister Pointer to the base address of usb debug port register interface.\r
305 @param Buffer Pointer to the buffer receiving data.\r
306 @param Length Number of bytes of the received data.\r
307 @param Token The token PID for each USB transaction.\r
308 @param Addr The usb device address for usb transaction.\r
309 @param Ep The endpoint for usb transaction.\r
310 @param DataToggle The toggle bit used at usb transaction.\r
311\r
312 @retval RETURN_SUCCESS The IN transaction is executed successfully.\r
313 @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.\r
314 @retval RETURN_DEVICE_ERROR The IN transaction comes across error.\r
315\r
316**/\r
317RETURN_STATUS\r
318EFIAPI\r
319UsbDebugPortIn (\r
320 IN USB_DEBUG_PORT_REGISTER *DebugPortRegister,\r
321 IN OUT UINT8 *Buffer,\r
322 OUT UINT8 *Length,\r
323 IN UINT8 Token,\r
324 IN UINT8 Addr,\r
325 IN UINT8 Ep,\r
326 IN UINT8 DataToggle\r
327 )\r
328{\r
329 UINTN Index;\r
330\r
331 if (Length == NULL) {\r
332 return RETURN_INVALID_PARAMETER;\r
333 }\r
334 *Length = 0;\r
335\r
336 DebugPortRegister->TokenPid = Token;\r
337 if (DataToggle != 0) {\r
338 DebugPortRegister->SendPid = DATA1_PID;\r
339 } else {\r
340 DebugPortRegister->SendPid = DATA0_PID;\r
341 }\r
342\r
343 DebugPortRegister->UsbAddress = (UINT8)(Addr & 0x7F);\r
344 DebugPortRegister->UsbEndPoint = (UINT8)(Ep & 0xF);\r
345\r
346 //\r
347 // Clearing W/R bit to indicate it's a READ operation\r
348 //\r
349 MmioAnd32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)~BIT4);\r
350\r
351 //\r
352 // Setting GO bit as well as clearing DONE bit\r
353 //\r
354 MmioOr32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)BIT5);\r
355\r
356 //\r
357 // Wait for completing the request\r
358 //\r
93c0bdec 359 while ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & (UINT32)BIT16) == 0) {\r
360 if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE))\r
361 != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE)) {\r
362 return RETURN_DEVICE_ERROR;\r
363 }\r
364 }\r
365 \r
366 //\r
367 // Clearing DONE bit by writing 1\r
368 //\r
369 MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT16);\r
18b144ea 370\r
371 //\r
372 // Check if the request is executed successfully or not.\r
373 //\r
374 if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & BIT6) {\r
375 return RETURN_DEVICE_ERROR;\r
376 }\r
377\r
378 //\r
379 // Make sure the received data are not beyond the allowable maximum length - 8 byte\r
380 //\r
381 if (((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & 0xF) > USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
382 return RETURN_DEVICE_ERROR;\r
383 }\r
384\r
385 *Length = (UINT8)(MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & 0xF);\r
ec99fa8e 386 if (*Length > 8) {\r
387 return RETURN_DEVICE_ERROR;\r
388 }\r
389\r
18b144ea 390 for (Index = 0; Index < *Length; Index++) {\r
391 Buffer[Index] = DebugPortRegister->DataBuffer[Index];\r
392 }\r
393 return RETURN_SUCCESS;\r
394}\r
395\r
396/**\r
397 Do a usb SETUP/OUT transaction by usb debug port.\r
398\r
399 @param DebugPortRegister Pointer to the base address of usb debug port register interface.\r
400 @param Buffer Pointer to the buffer receiving data.\r
401 @param Length Number of bytes of the received data.\r
402 @param Token The token PID for each USB transaction.\r
403 @param Addr The usb device address for usb transaction.\r
404 @param Ep The endpoint for usb transaction.\r
405 @param DataToggle The toggle bit used at usb transaction.\r
406\r
407 @retval RETURN_SUCCESS The IN transaction is executed successfully.\r
408 @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.\r
409 @retval RETURN_DEVICE_ERROR The IN transaction comes across error.\r
410\r
411**/\r
412RETURN_STATUS\r
413EFIAPI\r
414UsbDebugPortOut (\r
415 IN USB_DEBUG_PORT_REGISTER *DebugPortRegister,\r
416 IN UINT8 *Buffer,\r
417 IN UINT8 Length,\r
418 IN UINT8 Token,\r
419 IN UINT8 Addr,\r
420 IN UINT8 Ep,\r
421 IN UINT8 DataToggle\r
422 )\r
423{\r
424 UINT8 Index;\r
425\r
426 if (Length > 8) {\r
427 return RETURN_INVALID_PARAMETER;\r
428 }\r
429\r
430 DebugPortRegister->TokenPid = Token;\r
431 if (DataToggle != 0) {\r
432 DebugPortRegister->SendPid = DATA1_PID;\r
433 } else {\r
434 DebugPortRegister->SendPid = DATA0_PID;\r
435 }\r
436 DebugPortRegister->UsbAddress = (UINT8)(Addr & 0x7F);\r
437 DebugPortRegister->UsbEndPoint = (UINT8)(Ep & 0xF);\r
438\r
439 //\r
440 // Fill in the data length and corresponding data.\r
441 //\r
442 MmioAnd32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)~0xF);\r
443 MmioOr32((UINTN)&DebugPortRegister->ControlStatus, Length & 0xF);\r
444 for (Index = 0; Index < Length; Index++) {\r
445 DebugPortRegister->DataBuffer[Index] = Buffer[Index];\r
446 }\r
447\r
448 //\r
449 // Setting W/R bit to indicate it's a WRITE operation\r
450 //\r
451 MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT4);\r
452 //\r
453 // Setting GO bit as well as clearing DONE bit\r
454 //\r
455 MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT5);\r
456\r
457 //\r
458 // Wait for completing the request\r
459 //\r
93c0bdec 460 while ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & BIT16) == 0) {\r
461 if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE))\r
462 != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE)) {\r
463 return RETURN_DEVICE_ERROR;\r
464 }\r
465 }\r
466 \r
467 //\r
468 // Clearing DONE bit by writing 1\r
469 //\r
470 MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT16);\r
18b144ea 471\r
472 //\r
473 // Check if the request is executed successfully or not.\r
474 //\r
475 if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & BIT6) {\r
476 return RETURN_DEVICE_ERROR;\r
477 }\r
478\r
479 //\r
480 // Make sure the sent data are not beyond the allowable maximum length - 8 byte\r
481 //\r
482 if (((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & 0xF) > USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
483 return RETURN_DEVICE_ERROR;\r
484 }\r
485\r
486 return RETURN_SUCCESS;\r
487}\r
488\r
489/**\r
490 Do a usb control transfer by usb debug port.\r
491\r
492 @param DebugPortRegister Pointer to the base address of usb debug port register interface.\r
493 @param SetupPacket The token PID for each USB transaction.\r
494 @param Addr The usb device address for usb transaction.\r
495 @param Ep The endpoint for usb transaction.\r
496 @param Data Pointer to the buffer receiving data.\r
497 @param DataLength Number of bytes of the received data.\r
498\r
499 @retval RETURN_SUCCESS The IN transaction is executed successfully.\r
500 @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.\r
501 @retval RETURN_DEVICE_ERROR The IN transaction comes across error.\r
502\r
503**/\r
504RETURN_STATUS\r
505EFIAPI\r
506UsbDebugPortControlTransfer (\r
507 IN USB_DEBUG_PORT_REGISTER *DebugPortRegister,\r
508 IN USB_DEVICE_REQUEST *SetupPacket,\r
509 IN UINT8 Addr,\r
510 IN UINT8 Ep,\r
511 OUT UINT8 *Data,\r
512 IN OUT UINT8 *DataLength\r
513 )\r
514{\r
515 RETURN_STATUS Status;\r
516 UINT8 Temp;\r
83283ef1 517 UINT8 ReturnStatus[8];\r
18b144ea 518\r
519 //\r
520 // Setup Phase\r
521 //\r
522 Status = UsbDebugPortOut(DebugPortRegister, (UINT8 *)SetupPacket, (UINT8)sizeof(USB_DEVICE_REQUEST), SETUP_PID, Addr, Ep, 0);\r
523 if (RETURN_ERROR(Status)) {\r
524 return Status;\r
525 }\r
526\r
527 //\r
528 // Data Phase\r
529 //\r
83283ef1 530 if (DataLength != 0) {\r
18b144ea 531 if ((SetupPacket->RequestType & BIT7) != 0) {\r
532 //\r
533 // Get Data From Device\r
534 //\r
535 Status = UsbDebugPortIn(DebugPortRegister, Data, DataLength, INPUT_PID, Addr, Ep, 1);\r
536 if (RETURN_ERROR(Status)) {\r
537 return Status;\r
538 }\r
539 } else {\r
540 //\r
541 // Send Data To Device\r
542 //\r
543 Status = UsbDebugPortOut(DebugPortRegister, Data, *DataLength, OUTPUT_PID, Addr, Ep, 1);\r
544 if (RETURN_ERROR(Status)) {\r
545 return Status;\r
546 }\r
547 }\r
548 }\r
549\r
550 //\r
551 // Status Phase\r
552 //\r
553 if ((SetupPacket->RequestType & BIT7) != 0) {\r
554 //\r
555 // For READ operation, Data Toggle in Status Phase Should be 1.\r
556 //\r
557 Status = UsbDebugPortOut(DebugPortRegister, NULL, 0, OUTPUT_PID, Addr, Ep, 1);\r
558 } else {\r
559 //\r
560 // For WRITE operation, Data Toggle in Status Phase Should be 1.\r
561 //\r
83283ef1 562 Status = UsbDebugPortIn(DebugPortRegister, ReturnStatus, &Temp, INPUT_PID, Addr, Ep, 1);\r
18b144ea 563 }\r
564\r
565 return Status;\r
566}\r
567\r
568/**\r
569 Check if it needs to re-initialize usb debug port hardware.\r
570\r
571 During different phases switch, such as SEC to PEI or PEI to DXE or DXE to SMM, we should check\r
572 whether the usb debug port hardware configuration is changed. Such case can be triggerred by\r
573 Pci bus resource allocation and so on.\r
574\r
575 @param Handle Debug port handle.\r
576\r
577 @retval TRUE The usb debug port hardware configuration is changed.\r
578 @retval FALSE The usb debug port hardware configuration is not changed.\r
579\r
580**/\r
581BOOLEAN\r
582EFIAPI\r
583NeedReinitializeHardware(\r
584 IN USB_DEBUG_PORT_HANDLE *Handle\r
585 )\r
586{\r
587 UINT16 PciCmd;\r
93c0bdec 588 UINT32 UsbDebugPortMemoryBase;\r
589 UINT32 EhciMemoryBase;\r
18b144ea 590 BOOLEAN Status;\r
591 USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
592\r
593 Status = FALSE;\r
594\r
595 EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);\r
596 if (EhciMemoryBase != Handle->EhciMemoryBase) {\r
597 Handle->EhciMemoryBase = EhciMemoryBase;\r
598 Status = TRUE;\r
599 }\r
600\r
601 UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle->DebugPortBarNumber * 4);\r
602 if (UsbDebugPortMemoryBase != Handle->UsbDebugPortMemoryBase) {\r
603 Handle->UsbDebugPortMemoryBase = UsbDebugPortMemoryBase;\r
604 Status = TRUE;\r
605 }\r
606\r
607 //\r
608 // Enable Ehci Memory Space Access\r
609 //\r
610 PciCmd = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET);\r
611 if (((PciCmd & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((PciCmd & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {\r
93c0bdec 612 PciCmd |= EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER;\r
613 PciWrite16(PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET, PciCmd);\r
18b144ea 614 Status = TRUE;\r
615 }\r
616\r
617 //\r
93c0bdec 618 // If the owner and in_use bit is not set, it means system is doing cold/warm boot or EHCI host controller is reset by system software.\r
18b144ea 619 //\r
93c0bdec 620 UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(Handle->UsbDebugPortMemoryBase + Handle->DebugPortOffset);\r
621 if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_ENABLE | USB_DEBUG_PORT_IN_USE))\r
622 != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_ENABLE | USB_DEBUG_PORT_IN_USE)) {\r
623 Status = TRUE;\r
624 }\r
625\r
626 if (Handle->Initialized == USBDBG_RESET) {\r
627 Status = TRUE;\r
628 } else if (Handle->Initialized != USBDBG_INIT_DONE) {\r
18b144ea 629 Status = TRUE;\r
630 }\r
631 return Status;\r
632}\r
633\r
634/**\r
635 Initialize usb debug port hardware.\r
636\r
637 1. reset ehci host controller.\r
638 2. set right port to debug port.\r
639 3. find a usb debug device is attached by getting debug device descriptor.\r
640 4. set address for the usb debug device.\r
641 5. configure the usb debug device to debug mode.\r
642\r
643 @param Handle Debug port handle.\r
644\r
645 @retval TRUE The usb debug port hardware configuration is changed.\r
646 @retval FALSE The usb debug port hardware configuration is not changed.\r
647\r
648**/\r
649RETURN_STATUS\r
650EFIAPI\r
651InitializeUsbDebugHardware (\r
652 IN USB_DEBUG_PORT_HANDLE *Handle\r
653)\r
654{\r
655 RETURN_STATUS Status;\r
656 USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
657 USB_DEBUG_PORT_DESCRIPTOR UsbDebugPortDescriptor;\r
658 UINT16 PciCmd;\r
659 UINT32 *PortStatus;\r
660 UINT32 *UsbCmd;\r
661 UINT32 *UsbStatus;\r
662 UINT32 *UsbHCSParam;\r
663 UINT8 DebugPortNumber;\r
664 UINT8 Length;\r
665\r
93c0bdec 666 UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(Handle->UsbDebugPortMemoryBase + Handle->DebugPortOffset);\r
18b144ea 667 PciCmd = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET);\r
93c0bdec 668 UsbHCSParam = (UINT32 *)(UINTN)(Handle->EhciMemoryBase + 0x04);\r
669 UsbCmd = (UINT32 *)(UINTN)(Handle->EhciMemoryBase + 0x20);\r
670 UsbStatus = (UINT32 *)(UINTN)(Handle->EhciMemoryBase + 0x24);\r
18b144ea 671\r
672 //\r
93c0bdec 673 // Check if the debug port is enabled and owned by myself.\r
18b144ea 674 //\r
93c0bdec 675 if (((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE))\r
676 != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE)) || (Handle->Initialized == USBDBG_RESET)) {\r
677 //\r
b422b62c 678 // If the host controller is halted, then reset and restart it.\r
93c0bdec 679 //\r
b422b62c 680 if ((MmioRead32((UINTN)UsbStatus) & BIT12) != 0) {\r
681 //\r
682 // reset the host controller.\r
683 //\r
684 MmioOr32((UINTN)UsbCmd, BIT1);\r
685 //\r
686 // ensure that the host controller is reset.\r
687 //\r
688 while ((MmioRead32((UINTN)UsbCmd) & BIT1) != 0);\r
18b144ea 689\r
93c0bdec 690 MmioOr32((UINTN)UsbCmd, BIT0);\r
691 // ensure that the host controller is started (HALTED bit must be cleared)\r
b422b62c 692 while ((MmioRead32((UINTN)UsbStatus) & BIT12) != 0);\r
93c0bdec 693 }\r
18b144ea 694\r
93c0bdec 695 //\r
696 // First get the ownership of port 0.\r
697 //\r
698 MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE);\r
18b144ea 699\r
93c0bdec 700 MicroSecondDelay (200000);\r
18b144ea 701 }\r
18b144ea 702 //\r
703 // Find out which port is used as debug port.\r
704 //\r
705 DebugPortNumber = (UINT8)((MmioRead32((UINTN)UsbHCSParam) & 0x00F00000) >> 20);\r
706 //\r
93c0bdec 707 // Should find a device is connected at debug port\r
18b144ea 708 //\r
93c0bdec 709 PortStatus = (UINT32 *)(UINTN)(Handle->EhciMemoryBase + 0x64 + (DebugPortNumber - 1) * 4);\r
710 if (!(MmioRead32((UINTN)PortStatus) & BIT0)) {\r
711 Handle->Initialized = USBDBG_NO_DEV;\r
18b144ea 712 return RETURN_NOT_FOUND;\r
713 }\r
714\r
93c0bdec 715 if (Handle->Initialized != USBDBG_INIT_DONE) {\r
716 //\r
717 // Reset the debug port\r
718 //\r
719 MmioOr32((UINTN)PortStatus, BIT8);\r
720 MicroSecondDelay (500000);\r
721 MmioAnd32((UINTN)PortStatus, (UINT32)~BIT8);\r
722 while (MmioRead32((UINTN)PortStatus) & BIT8);\r
18b144ea 723\r
93c0bdec 724 //\r
725 // The port enabled bit should be set by HW.\r
726 //\r
727 if ((MmioRead32((UINTN)PortStatus) & BIT2) == 0) {\r
728 Handle->Initialized = USBDBG_NO_DBG_CAB;\r
729 return RETURN_DEVICE_ERROR;\r
730 }\r
18b144ea 731\r
93c0bdec 732 //\r
733 // Enable Usb Debug Port Capability\r
734 //\r
735 MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, USB_DEBUG_PORT_ENABLE);\r
18b144ea 736\r
93c0bdec 737 //\r
738 // initialize the data toggle used by bulk in/out endpoint.\r
739 //\r
740 Handle->BulkInToggle = 0;\r
741 Handle->BulkOutToggle = 0;\r
18b144ea 742\r
18b144ea 743 //\r
93c0bdec 744 // set usb debug device address as 0x7F.\r
18b144ea 745 //\r
93c0bdec 746 Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mSetDebugAddress, 0x0, 0x0, NULL, NULL);\r
747 if (RETURN_ERROR(Status)) {\r
748 //\r
749 // The device can not work well.\r
750 //\r
751 Handle->Initialized = USBDBG_NO_DBG_CAB;\r
752 return Status;\r
753 }\r
ec99fa8e 754\r
93c0bdec 755 //\r
756 // Start to communicate with Usb Debug Device to see if the attached device is usb debug device or not.\r
757 //\r
758 Length = (UINT8)sizeof (USB_DEBUG_PORT_DESCRIPTOR);\r
ec99fa8e 759\r
18b144ea 760 //\r
93c0bdec 761 // Get debug descriptor.\r
18b144ea 762 //\r
93c0bdec 763 Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mGetDebugDescriptor, 0x7F, 0x0, (UINT8*)&UsbDebugPortDescriptor, &Length);\r
764 if (RETURN_ERROR(Status)) {\r
765 //\r
766 // The device is not a usb debug device.\r
767 //\r
768 Handle->Initialized = USBDBG_NO_DBG_CAB;\r
769 return Status;\r
770 }\r
771\r
772 if (Length != sizeof(USB_DEBUG_PORT_DESCRIPTOR)) {\r
773 Handle->Initialized = USBDBG_NO_DBG_CAB;\r
774 return RETURN_DEVICE_ERROR;\r
775 }\r
776\r
777 //\r
778 // enable the usb debug feature.\r
779 //\r
780 Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mSetDebugFeature, 0x7F, 0x0, NULL, NULL);\r
781 if (RETURN_ERROR(Status)) {\r
782 //\r
783 // The device can not work well.\r
784 //\r
785 Handle->Initialized = USBDBG_NO_DBG_CAB;\r
786 return Status;\r
787 }\r
788 \r
789 Handle->Initialized = USBDBG_DBG_CAB;\r
18b144ea 790 }\r
791\r
792 //\r
93c0bdec 793 // Set initialized flag\r
18b144ea 794 //\r
93c0bdec 795 Handle->Initialized = USBDBG_INIT_DONE;\r
18b144ea 796\r
93c0bdec 797 return RETURN_SUCCESS;\r
18b144ea 798}\r
799\r
800/**\r
801 Read data from debug device and save the datas in buffer.\r
802\r
803 Reads NumberOfBytes data bytes from a debug device into the buffer\r
804 specified by Buffer. The number of bytes actually read is returned.\r
805 If the return value is less than NumberOfBytes, then the rest operation failed.\r
806 If NumberOfBytes is zero, then return 0.\r
807\r
808 @param Handle Debug port handle.\r
809 @param Buffer Pointer to the data buffer to store the data read from the debug device.\r
810 @param NumberOfBytes Number of bytes which will be read.\r
811 @param Timeout Timeout value for reading from debug device. It unit is Microsecond.\r
812\r
813 @retval 0 Read data failed, no data is to be read.\r
814 @retval >0 Actual number of bytes read from debug device.\r
815\r
816**/\r
817UINTN\r
818EFIAPI\r
819DebugPortReadBuffer (\r
820 IN DEBUG_PORT_HANDLE Handle,\r
821 IN UINT8 *Buffer,\r
822 IN UINTN NumberOfBytes,\r
823 IN UINTN Timeout\r
824 )\r
825{\r
826 USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
827 USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
828 RETURN_STATUS Status;\r
829 UINT8 Received;\r
830 UINTN Total;\r
831 UINTN Remaining;\r
832 UINT8 Index;\r
833 UINT8 Length;\r
b422b62c 834 UINT64 Begin;\r
835 UINT64 TimeoutTicker;\r
836 UINT64 TimerRound;\r
18b144ea 837\r
838 if (NumberOfBytes == 0 || Buffer == NULL) {\r
839 return 0;\r
840 }\r
841\r
842 Received = 0;\r
843 Total = 0;\r
844 Remaining = 0;\r
845\r
846 //\r
847 // If Handle is NULL, it means memory is ready for use.\r
848 // Use global variable to store handle value.\r
849 //\r
850 if (Handle == NULL) {\r
851 UsbDebugPortHandle = &mUsbDebugPortHandle;\r
852 } else {\r
853 UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;\r
854 }\r
855\r
856 if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
857 Status = InitializeUsbDebugHardware (UsbDebugPortHandle);\r
858 if (RETURN_ERROR(Status)) {\r
859 return 0;\r
860 }\r
861 }\r
862\r
93c0bdec 863 UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
18b144ea 864\r
865 //\r
866 // First read data from buffer, then read debug port hw to get received data.\r
867 //\r
868 if (UsbDebugPortHandle->DataCount > 0) {\r
869 if (NumberOfBytes <= UsbDebugPortHandle->DataCount) {\r
870 Total = NumberOfBytes;\r
871 } else {\r
872 Total = UsbDebugPortHandle->DataCount;\r
873 }\r
874\r
875 for (Index = 0; Index < Total; Index++) {\r
876 Buffer[Index] = UsbDebugPortHandle->Data[Index];\r
877 }\r
878\r
879 for (Index = 0; Index < UsbDebugPortHandle->DataCount - Total; Index++) {\r
880 if (Total + Index >= 8) {\r
881 return 0;\r
882 }\r
883 UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Total + Index];\r
884 }\r
885 UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - (UINT8)Total);\r
886 }\r
887\r
888 //\r
889 // If Timeout is equal to 0, then it means it should always wait until all datum required are received.\r
890 //\r
b422b62c 891 Begin = 0;\r
892 TimeoutTicker = 0; \r
893 TimerRound = 0;\r
894 if (Timeout != 0) {\r
895 Begin = GetPerformanceCounter ();\r
896 TimeoutTicker = DivU64x32 (\r
897 MultU64x64 (\r
898 UsbDebugPortHandle->TimerFrequency,\r
899 Timeout\r
900 ),\r
901 1000000u\r
902 );\r
903 TimerRound = DivU64x64Remainder (\r
904 TimeoutTicker,\r
905 DivU64x32 (UsbDebugPortHandle->TimerCycle, 2),\r
906 &TimeoutTicker\r
907 );\r
18b144ea 908 }\r
909\r
910 //\r
911 // Read remaining data by executing one or more usb debug transfer transactions at usb debug port hw.\r
912 //\r
b422b62c 913 while (Total < NumberOfBytes) {\r
914 if (Timeout != 0) {\r
915 if (TimerRound == 0) {\r
916 if (IsTimerTimeout (UsbDebugPortHandle, Begin, TimeoutTicker)) {\r
917 //\r
918 // If time out occurs.\r
919 //\r
920 return 0;\r
921 }\r
922 } else {\r
923 if (IsTimerTimeout (UsbDebugPortHandle, Begin, DivU64x32 (UsbDebugPortHandle->TimerCycle, 2))) {\r
924 TimerRound --;\r
925 }\r
926 }\r
927 }\r
18b144ea 928 Remaining = NumberOfBytes - Total;\r
929 if (Remaining >= USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
930 Status = UsbDebugPortIn(UsbDebugPortRegister, Buffer + Total, &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle);\r
931\r
932 if (RETURN_ERROR(Status)) {\r
933 return Total;\r
934 }\r
935 } else {\r
b422b62c 936 Status = UsbDebugPortIn(UsbDebugPortRegister, &UsbDebugPortHandle->Data[0], &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle);\r
18b144ea 937\r
b422b62c 938 if (RETURN_ERROR(Status)) {\r
939 return Total;\r
940 }\r
18b144ea 941\r
b422b62c 942 UsbDebugPortHandle->DataCount = Received;\r
18b144ea 943\r
b422b62c 944 if (Remaining <= Received) {\r
945 Length = (UINT8)Remaining;\r
946 } else {\r
947 Length = (UINT8)Received;\r
948 }\r
18b144ea 949\r
b422b62c 950 //\r
951 // Copy required data from the data buffer to user buffer.\r
952 //\r
953 for (Index = 0; Index < Length; Index++) {\r
954 (Buffer + Total)[Index] = UsbDebugPortHandle->Data[Index];\r
955 UsbDebugPortHandle->DataCount--;\r
956 }\r
18b144ea 957\r
b422b62c 958 //\r
959 // reorder the data buffer to make available data arranged from the beginning of the data buffer.\r
960 //\r
961 for (Index = 0; Index < Received - Length; Index++) {\r
962 if (Length + Index >= 8) {\r
963 return 0;\r
18b144ea 964 }\r
b422b62c 965 UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Length + Index];\r
18b144ea 966 }\r
b422b62c 967 //\r
968 // fixup the real received length in Buffer.\r
969 //\r
970 Received = Length;\r
971 }\r
972 UsbDebugPortHandle->BulkInToggle ^= 1;\r
973 Total += Received;\r
18b144ea 974 }\r
975\r
976 return Total;\r
977}\r
978\r
979/**\r
980 Write data from buffer to debug device.\r
981\r
982 Writes NumberOfBytes data bytes from Buffer to the debug device.\r
983 The number of bytes actually written to the debug device is returned.\r
984 If the return value is less than NumberOfBytes, then the write operation failed.\r
985 If NumberOfBytes is zero, then return 0.\r
986\r
987 @param Handle Debug port handle.\r
988 @param Buffer Pointer to the data buffer to be written.\r
989 @param NumberOfBytes Number of bytes to written to the debug device.\r
990\r
991 @retval 0 NumberOfBytes is 0.\r
992 @retval >0 The number of bytes written to the debug device.\r
993 If this value is less than NumberOfBytes, then the read operation failed.\r
994\r
995**/\r
996UINTN\r
997EFIAPI\r
998DebugPortWriteBuffer (\r
999 IN DEBUG_PORT_HANDLE Handle,\r
1000 IN UINT8 *Buffer,\r
1001 IN UINTN NumberOfBytes\r
1002 )\r
1003{\r
1004 USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
1005 USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
1006 RETURN_STATUS Status;\r
1007 UINT8 Sent;\r
1008 UINTN Total;\r
1009 UINT8 ReceivedPid;\r
1010\r
1011 if (NumberOfBytes == 0 || Buffer == NULL) {\r
1012 return 0;\r
1013 }\r
1014\r
1015 Sent = 0;\r
1016 Total = 0;\r
1017\r
1018 //\r
1019 // If Handle is NULL, it means memory is ready for use.\r
1020 // Use global variable to store handle value.\r
1021 //\r
1022 if (Handle == NULL) {\r
1023 UsbDebugPortHandle = &mUsbDebugPortHandle;\r
1024 } else {\r
1025 UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;\r
1026 }\r
1027\r
1028 if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
1029 Status = InitializeUsbDebugHardware (UsbDebugPortHandle);\r
1030 if (RETURN_ERROR(Status)) {\r
1031 return 0;\r
1032 }\r
1033 }\r
1034\r
93c0bdec 1035 UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
18b144ea 1036\r
1037 while ((Total < NumberOfBytes)) {\r
1038 if (NumberOfBytes - Total > USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
1039 Sent = USB_DEBUG_PORT_MAX_PACKET_SIZE;\r
1040 } else {\r
1041 Sent = (UINT8)(NumberOfBytes - Total);\r
1042 }\r
1043\r
1044 Status = UsbDebugPortOut(UsbDebugPortRegister, Buffer + Total, Sent, OUTPUT_PID, 0x7F, 0x01, UsbDebugPortHandle->BulkOutToggle);\r
1045\r
1046 if (RETURN_ERROR(Status)) {\r
1047 return Total;\r
1048 }\r
1049\r
1050 ReceivedPid = (MmioRead8((UINTN)&UsbDebugPortRegister->ReceivedPid));\r
1051 //\r
1052 // If received a NAK_PID on write transaction, it means the usb debug device is busy and can not handle this transaction.\r
1053 // should send the packet again.\r
1054 //\r
1055 if (ReceivedPid == NAK_PID) {\r
1056 Sent = 0;\r
1057 } else {\r
1058 UsbDebugPortHandle->BulkOutToggle ^= 1;\r
1059 }\r
1060 Total += Sent;\r
1061 }\r
1062 return Total;\r
1063}\r
1064\r
1065/**\r
1066 Polls a debug device to see if there is any data waiting to be read.\r
1067\r
1068 Polls a debug device to see if there is any data waiting to be read.\r
1069 If there is data waiting to be read from the debug device, then TRUE is returned.\r
1070 If there is no data waiting to be read from the debug device, then FALSE is returned.\r
1071\r
1072 @param Handle Debug port handle.\r
1073\r
1074 @retval TRUE Data is waiting to be read from the debug device.\r
1075 @retval FALSE There is no data waiting to be read from the serial device.\r
1076\r
1077**/\r
1078BOOLEAN\r
1079EFIAPI\r
1080DebugPortPollBuffer (\r
1081 IN DEBUG_PORT_HANDLE Handle\r
1082 )\r
1083{\r
1084 USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
1085 USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
1086 UINT8 Length;\r
1087 UINT8 Index;\r
1088 RETURN_STATUS Status;\r
1089\r
1090 //\r
1091 // If Handle is NULL, it means memory is ready for use.\r
1092 // Use global variable to store handle value.\r
1093 //\r
1094 if (Handle == NULL) {\r
1095 UsbDebugPortHandle = &mUsbDebugPortHandle;\r
1096 } else {\r
1097 UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;\r
1098 }\r
1099\r
1100 if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
1101 Status = InitializeUsbDebugHardware(UsbDebugPortHandle);\r
1102 if (RETURN_ERROR(Status)) {\r
1103 return FALSE;\r
1104 }\r
1105 }\r
1106\r
1107 //\r
1108 // If the data buffer is not empty, then return TRUE directly.\r
1109 // else initialize a usb read transaction and read data to the data buffer.\r
1110 //\r
1111 if (UsbDebugPortHandle->DataCount != 0) {\r
1112 return TRUE;\r
1113 }\r
1114\r
93c0bdec 1115 UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
18b144ea 1116\r
1117 UsbDebugPortRegister->TokenPid = INPUT_PID;\r
1118 if (UsbDebugPortHandle->BulkInToggle == 0) {\r
1119 UsbDebugPortRegister->SendPid = DATA0_PID;\r
1120 } else {\r
1121 UsbDebugPortRegister->SendPid = DATA1_PID;\r
1122 }\r
1123 UsbDebugPortRegister->UsbAddress = 0x7F;\r
1124 UsbDebugPortRegister->UsbEndPoint = 0x82 & 0x0F;\r
1125\r
1126 //\r
1127 // Clearing W/R bit to indicate it's a READ operation\r
1128 //\r
1129 MmioAnd32((UINTN)&UsbDebugPortRegister->ControlStatus, (UINT32)~BIT4);\r
1130 //\r
1131 // Setting GO bit as well as clearing DONE bit\r
1132 //\r
1133 MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, (UINT32)BIT5);\r
1134\r
1135 //\r
1136 // Wait for completing the request\r
1137 //\r
93c0bdec 1138 while ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (UINT32)BIT16) == 0) {\r
1139 if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE))\r
1140 != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE)) {\r
1141 return FALSE;\r
1142 }\r
1143 }\r
18b144ea 1144\r
1145 if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus)) & BIT6) {\r
1146 return FALSE;\r
1147 }\r
1148\r
1149 Length = (UINT8)(MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & 0xF);\r
1150\r
1151 if (Length > 8) {\r
1152 return FALSE;\r
1153 }\r
1154\r
1155 UsbDebugPortHandle->BulkInToggle ^= 1;\r
1156\r
1157 if (Length == 0) {\r
1158 return FALSE;\r
1159 }\r
1160\r
1161 for (Index = 0; Index < Length; Index++) {\r
1162 UsbDebugPortHandle->Data[Index] = UsbDebugPortRegister->DataBuffer[Index];\r
1163 }\r
1164 UsbDebugPortHandle->DataCount = Length;\r
1165\r
1166 return TRUE;\r
1167}\r
1168\r
1169/**\r
1170 Initialize the debug port.\r
1171\r
1172 If Function is not NULL, Debug Communication Libary will call this function\r
1173 by passing in the Context to be the first parameter. If needed, Debug Communication\r
1174 Library will create one debug port handle to be the second argument passing in\r
1175 calling the Function, otherwise it will pass NULL to be the second argument of\r
1176 Function.\r
1177\r
1178 If Function is NULL, and Context is not NULL, the Debug Communication Library could\r
1179 a) Return the same handle as passed in (as Context parameter).\r
1180 b) Ignore the input Context parameter and create new hanlde to be returned.\r
1181\r
1182 If parameter Function is NULL and Context is NULL, Debug Communication Library could\r
1183 created a new handle if needed and return it, otherwise it will return NULL.\r
1184\r
1185 @param[in] Context Context needed by callback function; it was optional.\r
1186 @param[in] Function Continue function called by Debug Communication library;\r
1187 it was optional.\r
1188\r
1189 @return The debug port handle created by Debug Communication Library if Function\r
1190 is not NULL.\r
1191\r
1192**/\r
1193DEBUG_PORT_HANDLE\r
1194EFIAPI\r
1195DebugPortInitialize (\r
1196 IN VOID *Context,\r
1197 IN DEBUG_PORT_CONTINUE Function\r
1198 )\r
1199{\r
1200 RETURN_STATUS Status;\r
1201 USB_DEBUG_PORT_HANDLE Handle;\r
b422b62c 1202 USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
1203 UINT64 TimerStartValue;\r
1204 UINT64 TimerEndValue;\r
1205\r //\r
1206 // Validate the PCD PcdDebugPortHandleBufferSize value \r
1207 //\r
1208 ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (USB_DEBUG_PORT_HANDLE));\r
1209\r
1210 if (Function == NULL && Context != NULL) {\r
1211 UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Context;\r
1212 } else {\r
1213 ZeroMem(&Handle, sizeof (USB_DEBUG_PORT_HANDLE));\r
1214 UsbDebugPortHandle = &Handle;\r
18b144ea 1215 }\r
1216\r
b422b62c 1217 UsbDebugPortHandle->TimerFrequency = GetPerformanceCounterProperties (\r
1218 &TimerStartValue,\r
1219 &TimerEndValue\r
1220 );\r
1221 DEBUG ((EFI_D_INFO, "USB Debug Port: TimerFrequency = 0x%lx\n", UsbDebugPortHandle->TimerFrequency)); \r
1222 DEBUG ((EFI_D_INFO, "USB Debug Port: TimerStartValue = 0x%lx\n", TimerStartValue)); \r
1223 DEBUG ((EFI_D_INFO, "USB Debug Port: TimerEndValue = 0x%lx\n", TimerEndValue)); \r
1224\r
1225 if (TimerEndValue < TimerStartValue) {\r
1226 UsbDebugPortHandle->TimerCountDown = TRUE;\r
1227 UsbDebugPortHandle->TimerCycle = TimerStartValue - TimerEndValue;\r
1228 } else {\r
1229 UsbDebugPortHandle->TimerCountDown = FALSE;\r
1230 UsbDebugPortHandle->TimerCycle = TimerEndValue - TimerStartValue;\r
1231 } \r
1232\r
1233 if (Function == NULL && Context != NULL) {\r
1234 return (DEBUG_PORT_HANDLE *) Context;\r
1235 }\r
18b144ea 1236\r
1237 Status = CalculateUsbDebugPortBar(&Handle.DebugPortOffset, &Handle.DebugPortBarNumber);\r
1238 if (RETURN_ERROR (Status)) {\r
93c0bdec 1239 DEBUG ((EFI_D_ERROR, "UsbDbg: the pci device pointed by PcdUsbEhciPciAddress is not EHCI host controller or does not support debug port capability!\n"));\r
e2104834 1240 goto Exit;\r
18b144ea 1241 }\r
1242\r
1243 Handle.EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);\r
1244\r
1245 if (Handle.EhciMemoryBase == 0) {\r
1246 //\r
1247 // Usb Debug Port MMIO Space Is Not Enabled. Assumption here that DebugPortBase is zero\r
1248 //\r
1249 PciWrite32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET, PcdGet32(PcdUsbEhciMemorySpaceBase));\r
1250 Handle.EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);\r
1251 }\r
1252\r
1253 Handle.UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4);\r
1254\r
1255 if (Handle.UsbDebugPortMemoryBase == 0) {\r
1256 //\r
1257 // Usb Debug Port MMIO Space Is Not Enabled. Assumption here that DebugPortBase is zero\r
1258 //\r
1259 PciWrite32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4, PcdGet32(PcdUsbDebugPortMemorySpaceBase));\r
1260 Handle.UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4);\r
1261 }\r
1262\r
93c0bdec 1263 Handle.Initialized = USBDBG_RESET;\r
18b144ea 1264\r
93c0bdec 1265 if (NeedReinitializeHardware(&Handle)) {\r
1266 DEBUG ((EFI_D_ERROR, "UsbDbg: Start EHCI debug port initialization!\n"));\r
1267 Status = InitializeUsbDebugHardware (&Handle);\r
1268 if (RETURN_ERROR(Status)) {\r
b422b62c 1269 DEBUG ((EFI_D_ERROR, "UsbDbg: Failed, please check if USB debug cable is plugged into EHCI debug port correctly!\n"));\r
93c0bdec 1270 goto Exit;\r
1271 }\r
1272 }\r
e2104834 1273\r
1274Exit:\r
1275\r
18b144ea 1276 if (Function != NULL) {\r
1277 Function (Context, &Handle);\r
1278 } else {\r
1279 CopyMem(&mUsbDebugPortHandle, &Handle, sizeof (USB_DEBUG_PORT_HANDLE));\r
1280 }\r
1281\r
1282 return (DEBUG_PORT_HANDLE)(UINTN)&mUsbDebugPortHandle;\r
1283}\r
1284\r