]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.c
Enhance DebugCommunicationLibUsb to reset the debug port when the PORT_ENABLE bit...
[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
93723244
RN
677 DEBUG ((\r
678 EFI_D_INFO,\r
679 "UsbDbg: Need to reset the host controller. ControlStatus = %08x\n",\r
680 MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus)\r
681 ));\r
93c0bdec 682 //\r
b422b62c 683 // If the host controller is halted, then reset and restart it.\r
93c0bdec 684 //\r
b422b62c 685 if ((MmioRead32((UINTN)UsbStatus) & BIT12) != 0) {\r
93723244 686 DEBUG ((EFI_D_INFO, "UsbDbg: Reset the host controller.\n"));\r
b422b62c 687 //\r
688 // reset the host controller.\r
689 //\r
690 MmioOr32((UINTN)UsbCmd, BIT1);\r
691 //\r
692 // ensure that the host controller is reset.\r
693 //\r
694 while ((MmioRead32((UINTN)UsbCmd) & BIT1) != 0);\r
18b144ea 695\r
93c0bdec 696 MmioOr32((UINTN)UsbCmd, BIT0);\r
697 // ensure that the host controller is started (HALTED bit must be cleared)\r
b422b62c 698 while ((MmioRead32((UINTN)UsbStatus) & BIT12) != 0);\r
93c0bdec 699 }\r
18b144ea 700\r
93c0bdec 701 //\r
702 // First get the ownership of port 0.\r
703 //\r
704 MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE);\r
18b144ea 705\r
93c0bdec 706 MicroSecondDelay (200000);\r
18b144ea 707 }\r
18b144ea 708 //\r
709 // Find out which port is used as debug port.\r
710 //\r
711 DebugPortNumber = (UINT8)((MmioRead32((UINTN)UsbHCSParam) & 0x00F00000) >> 20);\r
712 //\r
93c0bdec 713 // Should find a device is connected at debug port\r
18b144ea 714 //\r
93c0bdec 715 PortStatus = (UINT32 *)(UINTN)(Handle->EhciMemoryBase + 0x64 + (DebugPortNumber - 1) * 4);\r
716 if (!(MmioRead32((UINTN)PortStatus) & BIT0)) {\r
717 Handle->Initialized = USBDBG_NO_DEV;\r
18b144ea 718 return RETURN_NOT_FOUND;\r
719 }\r
720\r
93723244
RN
721 if (Handle->Initialized != USBDBG_INIT_DONE ||\r
722 (MmioRead32 ((UINTN) &UsbDebugPortRegister->ControlStatus) & USB_DEBUG_PORT_ENABLE) == 0) {\r
723 DEBUG ((EFI_D_INFO, "UsbDbg: Reset the debug port.\n"));\r
93c0bdec 724 //\r
725 // Reset the debug port\r
726 //\r
727 MmioOr32((UINTN)PortStatus, BIT8);\r
728 MicroSecondDelay (500000);\r
729 MmioAnd32((UINTN)PortStatus, (UINT32)~BIT8);\r
730 while (MmioRead32((UINTN)PortStatus) & BIT8);\r
18b144ea 731\r
93c0bdec 732 //\r
733 // The port enabled bit should be set by HW.\r
734 //\r
735 if ((MmioRead32((UINTN)PortStatus) & BIT2) == 0) {\r
736 Handle->Initialized = USBDBG_NO_DBG_CAB;\r
737 return RETURN_DEVICE_ERROR;\r
738 }\r
18b144ea 739\r
93c0bdec 740 //\r
741 // Enable Usb Debug Port Capability\r
742 //\r
743 MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, USB_DEBUG_PORT_ENABLE);\r
18b144ea 744\r
93c0bdec 745 //\r
746 // initialize the data toggle used by bulk in/out endpoint.\r
747 //\r
748 Handle->BulkInToggle = 0;\r
749 Handle->BulkOutToggle = 0;\r
18b144ea 750\r
18b144ea 751 //\r
93c0bdec 752 // set usb debug device address as 0x7F.\r
18b144ea 753 //\r
93c0bdec 754 Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mSetDebugAddress, 0x0, 0x0, NULL, NULL);\r
755 if (RETURN_ERROR(Status)) {\r
756 //\r
757 // The device can not work well.\r
758 //\r
759 Handle->Initialized = USBDBG_NO_DBG_CAB;\r
760 return Status;\r
761 }\r
ec99fa8e 762\r
93c0bdec 763 //\r
764 // Start to communicate with Usb Debug Device to see if the attached device is usb debug device or not.\r
765 //\r
766 Length = (UINT8)sizeof (USB_DEBUG_PORT_DESCRIPTOR);\r
ec99fa8e 767\r
18b144ea 768 //\r
93c0bdec 769 // Get debug descriptor.\r
18b144ea 770 //\r
93c0bdec 771 Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mGetDebugDescriptor, 0x7F, 0x0, (UINT8*)&UsbDebugPortDescriptor, &Length);\r
772 if (RETURN_ERROR(Status)) {\r
773 //\r
774 // The device is not a usb debug device.\r
775 //\r
776 Handle->Initialized = USBDBG_NO_DBG_CAB;\r
777 return Status;\r
778 }\r
779\r
780 if (Length != sizeof(USB_DEBUG_PORT_DESCRIPTOR)) {\r
781 Handle->Initialized = USBDBG_NO_DBG_CAB;\r
782 return RETURN_DEVICE_ERROR;\r
783 }\r
784\r
785 //\r
786 // enable the usb debug feature.\r
787 //\r
788 Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mSetDebugFeature, 0x7F, 0x0, NULL, NULL);\r
789 if (RETURN_ERROR(Status)) {\r
790 //\r
791 // The device can not work well.\r
792 //\r
793 Handle->Initialized = USBDBG_NO_DBG_CAB;\r
794 return Status;\r
795 }\r
796 \r
797 Handle->Initialized = USBDBG_DBG_CAB;\r
18b144ea 798 }\r
799\r
800 //\r
93c0bdec 801 // Set initialized flag\r
18b144ea 802 //\r
93c0bdec 803 Handle->Initialized = USBDBG_INIT_DONE;\r
18b144ea 804\r
93c0bdec 805 return RETURN_SUCCESS;\r
18b144ea 806}\r
807\r
808/**\r
809 Read data from debug device and save the datas in buffer.\r
810\r
811 Reads NumberOfBytes data bytes from a debug device into the buffer\r
812 specified by Buffer. The number of bytes actually read is returned.\r
813 If the return value is less than NumberOfBytes, then the rest operation failed.\r
814 If NumberOfBytes is zero, then return 0.\r
815\r
816 @param Handle Debug port handle.\r
817 @param Buffer Pointer to the data buffer to store the data read from the debug device.\r
818 @param NumberOfBytes Number of bytes which will be read.\r
819 @param Timeout Timeout value for reading from debug device. It unit is Microsecond.\r
820\r
821 @retval 0 Read data failed, no data is to be read.\r
822 @retval >0 Actual number of bytes read from debug device.\r
823\r
824**/\r
825UINTN\r
826EFIAPI\r
827DebugPortReadBuffer (\r
828 IN DEBUG_PORT_HANDLE Handle,\r
829 IN UINT8 *Buffer,\r
830 IN UINTN NumberOfBytes,\r
831 IN UINTN Timeout\r
832 )\r
833{\r
834 USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
835 USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
836 RETURN_STATUS Status;\r
837 UINT8 Received;\r
838 UINTN Total;\r
839 UINTN Remaining;\r
840 UINT8 Index;\r
841 UINT8 Length;\r
b422b62c 842 UINT64 Begin;\r
843 UINT64 TimeoutTicker;\r
844 UINT64 TimerRound;\r
18b144ea 845\r
846 if (NumberOfBytes == 0 || Buffer == NULL) {\r
847 return 0;\r
848 }\r
849\r
850 Received = 0;\r
851 Total = 0;\r
852 Remaining = 0;\r
853\r
854 //\r
855 // If Handle is NULL, it means memory is ready for use.\r
856 // Use global variable to store handle value.\r
857 //\r
858 if (Handle == NULL) {\r
859 UsbDebugPortHandle = &mUsbDebugPortHandle;\r
860 } else {\r
861 UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;\r
862 }\r
863\r
864 if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
865 Status = InitializeUsbDebugHardware (UsbDebugPortHandle);\r
866 if (RETURN_ERROR(Status)) {\r
867 return 0;\r
868 }\r
869 }\r
870\r
93c0bdec 871 UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
18b144ea 872\r
873 //\r
874 // First read data from buffer, then read debug port hw to get received data.\r
875 //\r
876 if (UsbDebugPortHandle->DataCount > 0) {\r
877 if (NumberOfBytes <= UsbDebugPortHandle->DataCount) {\r
878 Total = NumberOfBytes;\r
879 } else {\r
880 Total = UsbDebugPortHandle->DataCount;\r
881 }\r
882\r
883 for (Index = 0; Index < Total; Index++) {\r
884 Buffer[Index] = UsbDebugPortHandle->Data[Index];\r
885 }\r
886\r
887 for (Index = 0; Index < UsbDebugPortHandle->DataCount - Total; Index++) {\r
888 if (Total + Index >= 8) {\r
889 return 0;\r
890 }\r
891 UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Total + Index];\r
892 }\r
893 UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - (UINT8)Total);\r
894 }\r
895\r
896 //\r
897 // If Timeout is equal to 0, then it means it should always wait until all datum required are received.\r
898 //\r
b422b62c 899 Begin = 0;\r
900 TimeoutTicker = 0; \r
901 TimerRound = 0;\r
902 if (Timeout != 0) {\r
903 Begin = GetPerformanceCounter ();\r
904 TimeoutTicker = DivU64x32 (\r
905 MultU64x64 (\r
906 UsbDebugPortHandle->TimerFrequency,\r
907 Timeout\r
908 ),\r
909 1000000u\r
910 );\r
911 TimerRound = DivU64x64Remainder (\r
912 TimeoutTicker,\r
913 DivU64x32 (UsbDebugPortHandle->TimerCycle, 2),\r
914 &TimeoutTicker\r
915 );\r
18b144ea 916 }\r
917\r
918 //\r
919 // Read remaining data by executing one or more usb debug transfer transactions at usb debug port hw.\r
920 //\r
b422b62c 921 while (Total < NumberOfBytes) {\r
922 if (Timeout != 0) {\r
923 if (TimerRound == 0) {\r
924 if (IsTimerTimeout (UsbDebugPortHandle, Begin, TimeoutTicker)) {\r
925 //\r
926 // If time out occurs.\r
927 //\r
928 return 0;\r
929 }\r
930 } else {\r
931 if (IsTimerTimeout (UsbDebugPortHandle, Begin, DivU64x32 (UsbDebugPortHandle->TimerCycle, 2))) {\r
932 TimerRound --;\r
933 }\r
934 }\r
935 }\r
18b144ea 936 Remaining = NumberOfBytes - Total;\r
937 if (Remaining >= USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
938 Status = UsbDebugPortIn(UsbDebugPortRegister, Buffer + Total, &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle);\r
939\r
940 if (RETURN_ERROR(Status)) {\r
941 return Total;\r
942 }\r
943 } else {\r
b422b62c 944 Status = UsbDebugPortIn(UsbDebugPortRegister, &UsbDebugPortHandle->Data[0], &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle);\r
18b144ea 945\r
b422b62c 946 if (RETURN_ERROR(Status)) {\r
947 return Total;\r
948 }\r
18b144ea 949\r
b422b62c 950 UsbDebugPortHandle->DataCount = Received;\r
18b144ea 951\r
b422b62c 952 if (Remaining <= Received) {\r
953 Length = (UINT8)Remaining;\r
954 } else {\r
955 Length = (UINT8)Received;\r
956 }\r
18b144ea 957\r
b422b62c 958 //\r
959 // Copy required data from the data buffer to user buffer.\r
960 //\r
961 for (Index = 0; Index < Length; Index++) {\r
962 (Buffer + Total)[Index] = UsbDebugPortHandle->Data[Index];\r
963 UsbDebugPortHandle->DataCount--;\r
964 }\r
18b144ea 965\r
b422b62c 966 //\r
967 // reorder the data buffer to make available data arranged from the beginning of the data buffer.\r
968 //\r
969 for (Index = 0; Index < Received - Length; Index++) {\r
970 if (Length + Index >= 8) {\r
971 return 0;\r
18b144ea 972 }\r
b422b62c 973 UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Length + Index];\r
18b144ea 974 }\r
b422b62c 975 //\r
976 // fixup the real received length in Buffer.\r
977 //\r
978 Received = Length;\r
979 }\r
980 UsbDebugPortHandle->BulkInToggle ^= 1;\r
981 Total += Received;\r
18b144ea 982 }\r
983\r
984 return Total;\r
985}\r
986\r
987/**\r
988 Write data from buffer to debug device.\r
989\r
990 Writes NumberOfBytes data bytes from Buffer to the debug device.\r
991 The number of bytes actually written to the debug device is returned.\r
992 If the return value is less than NumberOfBytes, then the write operation failed.\r
993 If NumberOfBytes is zero, then return 0.\r
994\r
995 @param Handle Debug port handle.\r
996 @param Buffer Pointer to the data buffer to be written.\r
997 @param NumberOfBytes Number of bytes to written to the debug device.\r
998\r
999 @retval 0 NumberOfBytes is 0.\r
1000 @retval >0 The number of bytes written to the debug device.\r
1001 If this value is less than NumberOfBytes, then the read operation failed.\r
1002\r
1003**/\r
1004UINTN\r
1005EFIAPI\r
1006DebugPortWriteBuffer (\r
1007 IN DEBUG_PORT_HANDLE Handle,\r
1008 IN UINT8 *Buffer,\r
1009 IN UINTN NumberOfBytes\r
1010 )\r
1011{\r
1012 USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
1013 USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
1014 RETURN_STATUS Status;\r
1015 UINT8 Sent;\r
1016 UINTN Total;\r
1017 UINT8 ReceivedPid;\r
1018\r
1019 if (NumberOfBytes == 0 || Buffer == NULL) {\r
1020 return 0;\r
1021 }\r
1022\r
1023 Sent = 0;\r
1024 Total = 0;\r
1025\r
1026 //\r
1027 // If Handle is NULL, it means memory is ready for use.\r
1028 // Use global variable to store handle value.\r
1029 //\r
1030 if (Handle == NULL) {\r
1031 UsbDebugPortHandle = &mUsbDebugPortHandle;\r
1032 } else {\r
1033 UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;\r
1034 }\r
1035\r
1036 if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
1037 Status = InitializeUsbDebugHardware (UsbDebugPortHandle);\r
1038 if (RETURN_ERROR(Status)) {\r
1039 return 0;\r
1040 }\r
1041 }\r
1042\r
93c0bdec 1043 UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
18b144ea 1044\r
1045 while ((Total < NumberOfBytes)) {\r
1046 if (NumberOfBytes - Total > USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
1047 Sent = USB_DEBUG_PORT_MAX_PACKET_SIZE;\r
1048 } else {\r
1049 Sent = (UINT8)(NumberOfBytes - Total);\r
1050 }\r
1051\r
1052 Status = UsbDebugPortOut(UsbDebugPortRegister, Buffer + Total, Sent, OUTPUT_PID, 0x7F, 0x01, UsbDebugPortHandle->BulkOutToggle);\r
1053\r
1054 if (RETURN_ERROR(Status)) {\r
1055 return Total;\r
1056 }\r
1057\r
1058 ReceivedPid = (MmioRead8((UINTN)&UsbDebugPortRegister->ReceivedPid));\r
1059 //\r
1060 // If received a NAK_PID on write transaction, it means the usb debug device is busy and can not handle this transaction.\r
1061 // should send the packet again.\r
1062 //\r
1063 if (ReceivedPid == NAK_PID) {\r
1064 Sent = 0;\r
1065 } else {\r
1066 UsbDebugPortHandle->BulkOutToggle ^= 1;\r
1067 }\r
1068 Total += Sent;\r
1069 }\r
1070 return Total;\r
1071}\r
1072\r
1073/**\r
1074 Polls a debug device to see if there is any data waiting to be read.\r
1075\r
1076 Polls a debug device to see if there is any data waiting to be read.\r
1077 If there is data waiting to be read from the debug device, then TRUE is returned.\r
1078 If there is no data waiting to be read from the debug device, then FALSE is returned.\r
1079\r
1080 @param Handle Debug port handle.\r
1081\r
1082 @retval TRUE Data is waiting to be read from the debug device.\r
1083 @retval FALSE There is no data waiting to be read from the serial device.\r
1084\r
1085**/\r
1086BOOLEAN\r
1087EFIAPI\r
1088DebugPortPollBuffer (\r
1089 IN DEBUG_PORT_HANDLE Handle\r
1090 )\r
1091{\r
1092 USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
1093 USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
1094 UINT8 Length;\r
1095 UINT8 Index;\r
1096 RETURN_STATUS Status;\r
1097\r
1098 //\r
1099 // If Handle is NULL, it means memory is ready for use.\r
1100 // Use global variable to store handle value.\r
1101 //\r
1102 if (Handle == NULL) {\r
1103 UsbDebugPortHandle = &mUsbDebugPortHandle;\r
1104 } else {\r
1105 UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;\r
1106 }\r
1107\r
1108 if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
1109 Status = InitializeUsbDebugHardware(UsbDebugPortHandle);\r
1110 if (RETURN_ERROR(Status)) {\r
1111 return FALSE;\r
1112 }\r
1113 }\r
1114\r
1115 //\r
1116 // If the data buffer is not empty, then return TRUE directly.\r
1117 // else initialize a usb read transaction and read data to the data buffer.\r
1118 //\r
1119 if (UsbDebugPortHandle->DataCount != 0) {\r
1120 return TRUE;\r
1121 }\r
1122\r
93c0bdec 1123 UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
18b144ea 1124\r
1125 UsbDebugPortRegister->TokenPid = INPUT_PID;\r
1126 if (UsbDebugPortHandle->BulkInToggle == 0) {\r
1127 UsbDebugPortRegister->SendPid = DATA0_PID;\r
1128 } else {\r
1129 UsbDebugPortRegister->SendPid = DATA1_PID;\r
1130 }\r
1131 UsbDebugPortRegister->UsbAddress = 0x7F;\r
1132 UsbDebugPortRegister->UsbEndPoint = 0x82 & 0x0F;\r
1133\r
1134 //\r
1135 // Clearing W/R bit to indicate it's a READ operation\r
1136 //\r
1137 MmioAnd32((UINTN)&UsbDebugPortRegister->ControlStatus, (UINT32)~BIT4);\r
1138 //\r
1139 // Setting GO bit as well as clearing DONE bit\r
1140 //\r
1141 MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, (UINT32)BIT5);\r
1142\r
1143 //\r
1144 // Wait for completing the request\r
1145 //\r
93c0bdec 1146 while ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (UINT32)BIT16) == 0) {\r
1147 if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE))\r
1148 != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_ENABLE)) {\r
1149 return FALSE;\r
1150 }\r
1151 }\r
18b144ea 1152\r
1153 if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus)) & BIT6) {\r
1154 return FALSE;\r
1155 }\r
1156\r
1157 Length = (UINT8)(MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & 0xF);\r
1158\r
1159 if (Length > 8) {\r
1160 return FALSE;\r
1161 }\r
1162\r
1163 UsbDebugPortHandle->BulkInToggle ^= 1;\r
1164\r
1165 if (Length == 0) {\r
1166 return FALSE;\r
1167 }\r
1168\r
1169 for (Index = 0; Index < Length; Index++) {\r
1170 UsbDebugPortHandle->Data[Index] = UsbDebugPortRegister->DataBuffer[Index];\r
1171 }\r
1172 UsbDebugPortHandle->DataCount = Length;\r
1173\r
1174 return TRUE;\r
1175}\r
1176\r
1177/**\r
1178 Initialize the debug port.\r
1179\r
1180 If Function is not NULL, Debug Communication Libary will call this function\r
1181 by passing in the Context to be the first parameter. If needed, Debug Communication\r
1182 Library will create one debug port handle to be the second argument passing in\r
1183 calling the Function, otherwise it will pass NULL to be the second argument of\r
1184 Function.\r
1185\r
1186 If Function is NULL, and Context is not NULL, the Debug Communication Library could\r
1187 a) Return the same handle as passed in (as Context parameter).\r
1188 b) Ignore the input Context parameter and create new hanlde to be returned.\r
1189\r
1190 If parameter Function is NULL and Context is NULL, Debug Communication Library could\r
1191 created a new handle if needed and return it, otherwise it will return NULL.\r
1192\r
1193 @param[in] Context Context needed by callback function; it was optional.\r
1194 @param[in] Function Continue function called by Debug Communication library;\r
1195 it was optional.\r
1196\r
1197 @return The debug port handle created by Debug Communication Library if Function\r
1198 is not NULL.\r
1199\r
1200**/\r
1201DEBUG_PORT_HANDLE\r
1202EFIAPI\r
1203DebugPortInitialize (\r
1204 IN VOID *Context,\r
1205 IN DEBUG_PORT_CONTINUE Function\r
1206 )\r
1207{\r
1208 RETURN_STATUS Status;\r
1209 USB_DEBUG_PORT_HANDLE Handle;\r
b422b62c 1210 USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
1211 UINT64 TimerStartValue;\r
1212 UINT64 TimerEndValue;\r
1213\r //\r
1214 // Validate the PCD PcdDebugPortHandleBufferSize value \r
1215 //\r
1216 ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (USB_DEBUG_PORT_HANDLE));\r
1217\r
1218 if (Function == NULL && Context != NULL) {\r
1219 UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Context;\r
1220 } else {\r
1221 ZeroMem(&Handle, sizeof (USB_DEBUG_PORT_HANDLE));\r
1222 UsbDebugPortHandle = &Handle;\r
18b144ea 1223 }\r
1224\r
b422b62c 1225 UsbDebugPortHandle->TimerFrequency = GetPerformanceCounterProperties (\r
1226 &TimerStartValue,\r
1227 &TimerEndValue\r
1228 );\r
1229 DEBUG ((EFI_D_INFO, "USB Debug Port: TimerFrequency = 0x%lx\n", UsbDebugPortHandle->TimerFrequency)); \r
1230 DEBUG ((EFI_D_INFO, "USB Debug Port: TimerStartValue = 0x%lx\n", TimerStartValue)); \r
1231 DEBUG ((EFI_D_INFO, "USB Debug Port: TimerEndValue = 0x%lx\n", TimerEndValue)); \r
1232\r
1233 if (TimerEndValue < TimerStartValue) {\r
1234 UsbDebugPortHandle->TimerCountDown = TRUE;\r
1235 UsbDebugPortHandle->TimerCycle = TimerStartValue - TimerEndValue;\r
1236 } else {\r
1237 UsbDebugPortHandle->TimerCountDown = FALSE;\r
1238 UsbDebugPortHandle->TimerCycle = TimerEndValue - TimerStartValue;\r
1239 } \r
1240\r
1241 if (Function == NULL && Context != NULL) {\r
1242 return (DEBUG_PORT_HANDLE *) Context;\r
1243 }\r
18b144ea 1244\r
1245 Status = CalculateUsbDebugPortBar(&Handle.DebugPortOffset, &Handle.DebugPortBarNumber);\r
1246 if (RETURN_ERROR (Status)) {\r
93c0bdec 1247 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 1248 goto Exit;\r
18b144ea 1249 }\r
1250\r
1251 Handle.EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);\r
1252\r
1253 if (Handle.EhciMemoryBase == 0) {\r
1254 //\r
1255 // Usb Debug Port MMIO Space Is Not Enabled. Assumption here that DebugPortBase is zero\r
1256 //\r
1257 PciWrite32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET, PcdGet32(PcdUsbEhciMemorySpaceBase));\r
1258 Handle.EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);\r
1259 }\r
1260\r
1261 Handle.UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4);\r
1262\r
1263 if (Handle.UsbDebugPortMemoryBase == 0) {\r
1264 //\r
1265 // Usb Debug Port MMIO Space Is Not Enabled. Assumption here that DebugPortBase is zero\r
1266 //\r
1267 PciWrite32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4, PcdGet32(PcdUsbDebugPortMemorySpaceBase));\r
1268 Handle.UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4);\r
1269 }\r
1270\r
93c0bdec 1271 Handle.Initialized = USBDBG_RESET;\r
18b144ea 1272\r
93c0bdec 1273 if (NeedReinitializeHardware(&Handle)) {\r
1274 DEBUG ((EFI_D_ERROR, "UsbDbg: Start EHCI debug port initialization!\n"));\r
1275 Status = InitializeUsbDebugHardware (&Handle);\r
1276 if (RETURN_ERROR(Status)) {\r
b422b62c 1277 DEBUG ((EFI_D_ERROR, "UsbDbg: Failed, please check if USB debug cable is plugged into EHCI debug port correctly!\n"));\r
93c0bdec 1278 goto Exit;\r
1279 }\r
1280 }\r
e2104834 1281\r
1282Exit:\r
1283\r
18b144ea 1284 if (Function != NULL) {\r
1285 Function (Context, &Handle);\r
1286 } else {\r
1287 CopyMem(&mUsbDebugPortHandle, &Handle, sizeof (USB_DEBUG_PORT_HANDLE));\r
1288 }\r
1289\r
1290 return (DEBUG_PORT_HANDLE)(UINTN)&mUsbDebugPortHandle;\r
1291}\r
1292\r