]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.c
Check the return status of booting against EFI_SUCCESS instead of using EFI_ERROR...
[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
83283ef1 4 Copyright (c) 2010 - 2011, 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
102#pragma pack(1)\r
103//\r
104// The internal data structure of DEBUG_PORT_HANDLE, which stores some\r
105// important datum which are used across various phases.\r
106//\r
107typedef struct _USB_DEBUG_PORT_HANDLE{\r
108 //\r
109 // The usb debug port memory BAR number in EHCI configuration space.\r
110 //\r
111 UINT8 DebugPortBarNumber;\r
e2104834 112 BOOLEAN Initialized;\r
18b144ea 113 //\r
114 // The offset of usb debug port registers in EHCI memory range.\r
115 //\r
116 UINT16 DebugPortOffset;\r
117 //\r
118 // The usb debug port memory BAR address.\r
119 //\r
120 UINTN UsbDebugPortMemoryBase;\r
121 //\r
122 // The EHCI memory BAR address.\r
123 //\r
124 UINTN EhciMemoryBase;\r
125 //\r
126 // The Bulk In endpoint toggle bit.\r
127 //\r
128 UINT8 BulkInToggle;\r
129 //\r
130 // The Bulk Out endpoint toggle bit.\r
131 //\r
132 UINT8 BulkOutToggle;\r
133 //\r
134 // The available data length in the following data buffer.\r
135 //\r
136 UINT8 DataCount;\r
137 //\r
138 // The data buffer. Maximum length is 8 bytes.\r
139 //\r
140 UINT8 Data[8];\r
141} USB_DEBUG_PORT_HANDLE;\r
142#pragma pack()\r
143\r
144//\r
145// The global variable which can be used after memory is ready.\r
146//\r
147USB_DEBUG_PORT_HANDLE mUsbDebugPortHandle;\r
148\r
149/**\r
150 Calculate the usb debug port bar address.\r
151\r
152 @param DebugPortOffset Get usb debug port offset in the usb debug port memory space.\r
153 @param DebugPortBarNumbar Get the bar number at which usb debug port is located.\r
154\r
155 @retval RETURN_UNSUPPORTED The usb host controller does not supported usb debug port capability.\r
156 @retval RETURN_SUCCESS Get bar and offset successfully.\r
157\r
158**/\r
159RETURN_STATUS\r
160EFIAPI\r
161CalculateUsbDebugPortBar (\r
162 OUT UINT16 *DebugPortOffset,\r
163 OUT UINT8 *DebugPortBarNumbar\r
164 )\r
165{\r
166 UINT16 PciStatus;\r
167 UINT8 CapabilityPtr;\r
168 UINT8 CapabilityId;\r
169\r
170 //\r
171 // Enable Ehci Host Controller MMIO Space.\r
172 //\r
173 PciStatus = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_PRIMARY_STATUS_OFFSET);\r
174\r
175 if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {\r
176 //\r
177 // The Pci Device Doesn't Support Capability Pointer.\r
178 //\r
179 return RETURN_UNSUPPORTED;\r
180 }\r
181\r
182 //\r
183 // Get Pointer To Capability List\r
184 //\r
185 CapabilityPtr = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + PCI_CAPBILITY_POINTER_OFFSET);\r
186\r
187 //\r
188 // Find Capability ID 0xA, Which Is For Debug Port\r
189 //\r
190 while (CapabilityPtr != 0) {\r
191 CapabilityId = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr);\r
192 if (CapabilityId == PCI_CAPABILITY_ID_DEBUG_PORT) {\r
193 break;\r
194 }\r
195 CapabilityPtr = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 1);\r
196 }\r
197\r
198 //\r
199 // No Debug Port Capability Found\r
200 //\r
201 if (CapabilityPtr == 0) {\r
202 return RETURN_UNSUPPORTED;\r
203 }\r
204\r
205 //\r
206 // Get The Base Address Of Debug Port Register In Debug Port Capability Register\r
207 //\r
208 *DebugPortOffset = (UINT16)(PciRead16(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 2) & 0x1FFF);\r
209 *DebugPortBarNumbar = (UINT8)((PciRead16(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 2) >> 13) - 1);\r
210\r
211 return RETURN_SUCCESS;\r
212}\r
213\r
214/**\r
215 Do a usb IN transaction by usb debug port.\r
216\r
217 @param DebugPortRegister Pointer to the base address of usb debug port register interface.\r
218 @param Buffer Pointer to the buffer receiving data.\r
219 @param Length Number of bytes of the received data.\r
220 @param Token The token PID for each USB transaction.\r
221 @param Addr The usb device address for usb transaction.\r
222 @param Ep The endpoint for usb transaction.\r
223 @param DataToggle The toggle bit used at usb transaction.\r
224\r
225 @retval RETURN_SUCCESS The IN transaction is executed successfully.\r
226 @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.\r
227 @retval RETURN_DEVICE_ERROR The IN transaction comes across error.\r
228\r
229**/\r
230RETURN_STATUS\r
231EFIAPI\r
232UsbDebugPortIn (\r
233 IN USB_DEBUG_PORT_REGISTER *DebugPortRegister,\r
234 IN OUT UINT8 *Buffer,\r
235 OUT UINT8 *Length,\r
236 IN UINT8 Token,\r
237 IN UINT8 Addr,\r
238 IN UINT8 Ep,\r
239 IN UINT8 DataToggle\r
240 )\r
241{\r
242 UINTN Index;\r
243\r
244 if (Length == NULL) {\r
245 return RETURN_INVALID_PARAMETER;\r
246 }\r
247 *Length = 0;\r
248\r
249 DebugPortRegister->TokenPid = Token;\r
250 if (DataToggle != 0) {\r
251 DebugPortRegister->SendPid = DATA1_PID;\r
252 } else {\r
253 DebugPortRegister->SendPid = DATA0_PID;\r
254 }\r
255\r
256 DebugPortRegister->UsbAddress = (UINT8)(Addr & 0x7F);\r
257 DebugPortRegister->UsbEndPoint = (UINT8)(Ep & 0xF);\r
258\r
259 //\r
260 // Clearing W/R bit to indicate it's a READ operation\r
261 //\r
262 MmioAnd32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)~BIT4);\r
263\r
264 //\r
265 // Setting GO bit as well as clearing DONE bit\r
266 //\r
267 MmioOr32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)BIT5);\r
268\r
269 //\r
270 // Wait for completing the request\r
271 //\r
272 while ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & (UINT32)BIT16) == 0);\r
273\r
274 //\r
275 // Check if the request is executed successfully or not.\r
276 //\r
277 if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & BIT6) {\r
278 return RETURN_DEVICE_ERROR;\r
279 }\r
280\r
281 //\r
282 // Make sure the received data are not beyond the allowable maximum length - 8 byte\r
283 //\r
284 if (((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & 0xF) > USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
285 return RETURN_DEVICE_ERROR;\r
286 }\r
287\r
288 *Length = (UINT8)(MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & 0xF);\r
ec99fa8e 289 if (*Length > 8) {\r
290 return RETURN_DEVICE_ERROR;\r
291 }\r
292\r
18b144ea 293 for (Index = 0; Index < *Length; Index++) {\r
294 Buffer[Index] = DebugPortRegister->DataBuffer[Index];\r
295 }\r
296 return RETURN_SUCCESS;\r
297}\r
298\r
299/**\r
300 Do a usb SETUP/OUT transaction by usb debug port.\r
301\r
302 @param DebugPortRegister Pointer to the base address of usb debug port register interface.\r
303 @param Buffer Pointer to the buffer receiving data.\r
304 @param Length Number of bytes of the received data.\r
305 @param Token The token PID for each USB transaction.\r
306 @param Addr The usb device address for usb transaction.\r
307 @param Ep The endpoint for usb transaction.\r
308 @param DataToggle The toggle bit used at usb transaction.\r
309\r
310 @retval RETURN_SUCCESS The IN transaction is executed successfully.\r
311 @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.\r
312 @retval RETURN_DEVICE_ERROR The IN transaction comes across error.\r
313\r
314**/\r
315RETURN_STATUS\r
316EFIAPI\r
317UsbDebugPortOut (\r
318 IN USB_DEBUG_PORT_REGISTER *DebugPortRegister,\r
319 IN UINT8 *Buffer,\r
320 IN UINT8 Length,\r
321 IN UINT8 Token,\r
322 IN UINT8 Addr,\r
323 IN UINT8 Ep,\r
324 IN UINT8 DataToggle\r
325 )\r
326{\r
327 UINT8 Index;\r
328\r
329 if (Length > 8) {\r
330 return RETURN_INVALID_PARAMETER;\r
331 }\r
332\r
333 DebugPortRegister->TokenPid = Token;\r
334 if (DataToggle != 0) {\r
335 DebugPortRegister->SendPid = DATA1_PID;\r
336 } else {\r
337 DebugPortRegister->SendPid = DATA0_PID;\r
338 }\r
339 DebugPortRegister->UsbAddress = (UINT8)(Addr & 0x7F);\r
340 DebugPortRegister->UsbEndPoint = (UINT8)(Ep & 0xF);\r
341\r
342 //\r
343 // Fill in the data length and corresponding data.\r
344 //\r
345 MmioAnd32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)~0xF);\r
346 MmioOr32((UINTN)&DebugPortRegister->ControlStatus, Length & 0xF);\r
347 for (Index = 0; Index < Length; Index++) {\r
348 DebugPortRegister->DataBuffer[Index] = Buffer[Index];\r
349 }\r
350\r
351 //\r
352 // Setting W/R bit to indicate it's a WRITE operation\r
353 //\r
354 MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT4);\r
355 //\r
356 // Setting GO bit as well as clearing DONE bit\r
357 //\r
358 MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT5);\r
359\r
360 //\r
361 // Wait for completing the request\r
362 //\r
363 while ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & BIT16) == 0);\r
364\r
365 //\r
366 // Check if the request is executed successfully or not.\r
367 //\r
368 if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & BIT6) {\r
369 return RETURN_DEVICE_ERROR;\r
370 }\r
371\r
372 //\r
373 // Make sure the sent data are not beyond the allowable maximum length - 8 byte\r
374 //\r
375 if (((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & 0xF) > USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
376 return RETURN_DEVICE_ERROR;\r
377 }\r
378\r
379 return RETURN_SUCCESS;\r
380}\r
381\r
382/**\r
383 Do a usb control transfer by usb debug port.\r
384\r
385 @param DebugPortRegister Pointer to the base address of usb debug port register interface.\r
386 @param SetupPacket The token PID for each USB transaction.\r
387 @param Addr The usb device address for usb transaction.\r
388 @param Ep The endpoint for usb transaction.\r
389 @param Data Pointer to the buffer receiving data.\r
390 @param DataLength Number of bytes of the received data.\r
391\r
392 @retval RETURN_SUCCESS The IN transaction is executed successfully.\r
393 @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.\r
394 @retval RETURN_DEVICE_ERROR The IN transaction comes across error.\r
395\r
396**/\r
397RETURN_STATUS\r
398EFIAPI\r
399UsbDebugPortControlTransfer (\r
400 IN USB_DEBUG_PORT_REGISTER *DebugPortRegister,\r
401 IN USB_DEVICE_REQUEST *SetupPacket,\r
402 IN UINT8 Addr,\r
403 IN UINT8 Ep,\r
404 OUT UINT8 *Data,\r
405 IN OUT UINT8 *DataLength\r
406 )\r
407{\r
408 RETURN_STATUS Status;\r
409 UINT8 Temp;\r
83283ef1 410 UINT8 ReturnStatus[8];\r
18b144ea 411\r
412 //\r
413 // Setup Phase\r
414 //\r
415 Status = UsbDebugPortOut(DebugPortRegister, (UINT8 *)SetupPacket, (UINT8)sizeof(USB_DEVICE_REQUEST), SETUP_PID, Addr, Ep, 0);\r
416 if (RETURN_ERROR(Status)) {\r
417 return Status;\r
418 }\r
419\r
420 //\r
421 // Data Phase\r
422 //\r
83283ef1 423 if (DataLength != 0) {\r
18b144ea 424 if ((SetupPacket->RequestType & BIT7) != 0) {\r
425 //\r
426 // Get Data From Device\r
427 //\r
428 Status = UsbDebugPortIn(DebugPortRegister, Data, DataLength, INPUT_PID, Addr, Ep, 1);\r
429 if (RETURN_ERROR(Status)) {\r
430 return Status;\r
431 }\r
432 } else {\r
433 //\r
434 // Send Data To Device\r
435 //\r
436 Status = UsbDebugPortOut(DebugPortRegister, Data, *DataLength, OUTPUT_PID, Addr, Ep, 1);\r
437 if (RETURN_ERROR(Status)) {\r
438 return Status;\r
439 }\r
440 }\r
441 }\r
442\r
443 //\r
444 // Status Phase\r
445 //\r
446 if ((SetupPacket->RequestType & BIT7) != 0) {\r
447 //\r
448 // For READ operation, Data Toggle in Status Phase Should be 1.\r
449 //\r
450 Status = UsbDebugPortOut(DebugPortRegister, NULL, 0, OUTPUT_PID, Addr, Ep, 1);\r
451 } else {\r
452 //\r
453 // For WRITE operation, Data Toggle in Status Phase Should be 1.\r
454 //\r
83283ef1 455 Status = UsbDebugPortIn(DebugPortRegister, ReturnStatus, &Temp, INPUT_PID, Addr, Ep, 1);\r
18b144ea 456 }\r
457\r
458 return Status;\r
459}\r
460\r
461/**\r
462 Check if it needs to re-initialize usb debug port hardware.\r
463\r
464 During different phases switch, such as SEC to PEI or PEI to DXE or DXE to SMM, we should check\r
465 whether the usb debug port hardware configuration is changed. Such case can be triggerred by\r
466 Pci bus resource allocation and so on.\r
467\r
468 @param Handle Debug port handle.\r
469\r
470 @retval TRUE The usb debug port hardware configuration is changed.\r
471 @retval FALSE The usb debug port hardware configuration is not changed.\r
472\r
473**/\r
474BOOLEAN\r
475EFIAPI\r
476NeedReinitializeHardware(\r
477 IN USB_DEBUG_PORT_HANDLE *Handle\r
478 )\r
479{\r
480 UINT16 PciCmd;\r
481 UINTN UsbDebugPortMemoryBase;\r
482 UINTN EhciMemoryBase;\r
483 BOOLEAN Status;\r
484 USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
485\r
486 Status = FALSE;\r
487\r
488 EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);\r
489 if (EhciMemoryBase != Handle->EhciMemoryBase) {\r
490 Handle->EhciMemoryBase = EhciMemoryBase;\r
491 Status = TRUE;\r
492 }\r
493\r
494 UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle->DebugPortBarNumber * 4);\r
495 if (UsbDebugPortMemoryBase != Handle->UsbDebugPortMemoryBase) {\r
496 Handle->UsbDebugPortMemoryBase = UsbDebugPortMemoryBase;\r
497 Status = TRUE;\r
498 }\r
499\r
500 //\r
501 // Enable Ehci Memory Space Access\r
502 //\r
503 PciCmd = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET);\r
504 if (((PciCmd & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((PciCmd & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {\r
505 Status = TRUE;\r
506 }\r
507\r
508 //\r
509 // Check if the debug port is enabled and owned by myself.\r
510 //\r
511 UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(Handle->UsbDebugPortMemoryBase + Handle->DebugPortOffset);\r
512 if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) &\r
513 (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_ENABLE | USB_DEBUG_PORT_IN_USE)) == 0) {\r
514 Status = TRUE;\r
515 }\r
516 return Status;\r
517}\r
518\r
519/**\r
520 Initialize usb debug port hardware.\r
521\r
522 1. reset ehci host controller.\r
523 2. set right port to debug port.\r
524 3. find a usb debug device is attached by getting debug device descriptor.\r
525 4. set address for the usb debug device.\r
526 5. configure the usb debug device to debug mode.\r
527\r
528 @param Handle Debug port handle.\r
529\r
530 @retval TRUE The usb debug port hardware configuration is changed.\r
531 @retval FALSE The usb debug port hardware configuration is not changed.\r
532\r
533**/\r
534RETURN_STATUS\r
535EFIAPI\r
536InitializeUsbDebugHardware (\r
537 IN USB_DEBUG_PORT_HANDLE *Handle\r
538)\r
539{\r
540 RETURN_STATUS Status;\r
541 USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
542 USB_DEBUG_PORT_DESCRIPTOR UsbDebugPortDescriptor;\r
543 UINT16 PciCmd;\r
544 UINT32 *PortStatus;\r
545 UINT32 *UsbCmd;\r
546 UINT32 *UsbStatus;\r
547 UINT32 *UsbHCSParam;\r
548 UINT8 DebugPortNumber;\r
549 UINT8 Length;\r
550\r
551 UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(Handle->UsbDebugPortMemoryBase + Handle->DebugPortOffset);\r
552 PciCmd = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET);\r
553 UsbHCSParam = (UINT32 *)(Handle->EhciMemoryBase + 0x04);\r
554 UsbCmd = (UINT32 *)(Handle->EhciMemoryBase + 0x20);\r
555 UsbStatus = (UINT32 *)(Handle->EhciMemoryBase + 0x24);\r
556\r
557 //\r
558 // initialize the data toggle used by bulk in/out endpoint.\r
559 //\r
560 Handle->BulkInToggle = 0;\r
561 Handle->BulkOutToggle = 0;\r
562\r
563 //\r
564 // Enable Ehci Memory Space Access\r
565 //\r
566 if (((PciCmd & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((PciCmd & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {\r
567 PciCmd |= EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER;\r
568 PciWrite16(PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET, PciCmd);\r
569 }\r
570\r
571 //\r
572 // If the host controller is not halted, then halt it.\r
573 //\r
574 if ((MmioRead32((UINTN)UsbStatus) & BIT12) == 0) {\r
575 MmioAnd32((UINTN)UsbCmd, (UINT32)~BIT0);\r
576 while ((MmioRead32((UINTN)UsbStatus) & BIT12) == 0);\r
577 }\r
578 //\r
579 // reset the host controller.\r
580 //\r
581 MmioOr32((UINTN)UsbCmd, BIT1);\r
582 //\r
583 // ensure that the host controller is reset.\r
584 //\r
585 while (MmioRead32((UINTN)UsbCmd) & BIT1);\r
586\r
587 //\r
588 // Start the host controller if it's not running\r
589 //\r
590 if (MmioRead32((UINTN)UsbStatus) & BIT12) {\r
591 MmioOr32((UINTN)UsbCmd, BIT0);\r
592 // ensure that the host controller is started (HALTED bit must be cleared)\r
593 while (MmioRead32((UINTN)UsbStatus) & BIT12);\r
594 }\r
595\r
596 //\r
597 // First get the ownership of port 0.\r
598 //\r
599 MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, USB_DEBUG_PORT_OWNER);\r
600\r
601 MicroSecondDelay (200000);\r
602\r
603 //\r
604 // Find out which port is used as debug port.\r
605 //\r
606 DebugPortNumber = (UINT8)((MmioRead32((UINTN)UsbHCSParam) & 0x00F00000) >> 20);\r
607 //\r
608 // Should find a non low-speed device is connected\r
609 //\r
610 PortStatus = (UINT32 *)(Handle->EhciMemoryBase + 0x64 + (DebugPortNumber - 1) * 4);\r
611 if (!(MmioRead32((UINTN)PortStatus) & BIT0) || ((MmioRead32((UINTN)PortStatus) & USB_PORT_LINE_STATUS_MASK) == USB_PORT_LINE_STATUS_LS)) {\r
612 return RETURN_NOT_FOUND;\r
613 }\r
614\r
615 //\r
616 // Reset the debug port\r
617 //\r
618 MmioOr32((UINTN)PortStatus, BIT8);\r
619 MicroSecondDelay (200000);\r
620 MmioAnd32((UINTN)PortStatus, (UINT32)~BIT8);\r
621 while (MmioRead32((UINTN)PortStatus) & BIT8);\r
622\r
623 //\r
624 // The port enabled bit should be set by HW.\r
625 //\r
626 if ((MmioRead32((UINTN)PortStatus) & BIT2) == 0) {\r
627 return RETURN_DEVICE_ERROR;\r
628 }\r
629\r
630 //\r
631 // Enable Usb Debug Port Capability\r
632 //\r
633 MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, USB_DEBUG_PORT_ENABLE | USB_DEBUG_PORT_IN_USE);\r
634\r
635 //\r
636 // Start to communicate with Usb Debug Device to see if the attached device is usb debug device or not.\r
637 //\r
638 Length = (UINT8)sizeof (USB_DEBUG_PORT_DESCRIPTOR);\r
639\r
640 //\r
641 // It's not a dedicated usb debug device, should use address 0 to get debug descriptor.\r
642 //\r
643 Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mGetDebugDescriptor, 0x0, 0x0, (UINT8*)&UsbDebugPortDescriptor, &Length);\r
644 if (RETURN_ERROR(Status)) {\r
645 //\r
646 // The device is not a usb debug device.\r
647 //\r
648 return Status;\r
649 }\r
ec99fa8e 650\r
651 if (Length != sizeof(USB_DEBUG_PORT_DESCRIPTOR)) {\r
652 return RETURN_DEVICE_ERROR;\r
653 }\r
654\r
18b144ea 655 //\r
656 // set usb debug device address as 0x7F.\r
657 //\r
83283ef1 658 Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mSetDebugAddress, 0x0, 0x0, NULL, NULL);\r
18b144ea 659 if (RETURN_ERROR(Status)) {\r
660 //\r
661 // The device can not work well.\r
662 //\r
663 return Status;\r
664 }\r
665\r
666 //\r
667 // enable the usb debug feature.\r
668 //\r
669 Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mSetDebugFeature, 0x7F, 0x0, NULL, NULL);\r
670\r
671 return Status;\r
672}\r
673\r
674/**\r
675 Read data from debug device and save the datas in buffer.\r
676\r
677 Reads NumberOfBytes data bytes from a debug device into the buffer\r
678 specified by Buffer. The number of bytes actually read is returned.\r
679 If the return value is less than NumberOfBytes, then the rest operation failed.\r
680 If NumberOfBytes is zero, then return 0.\r
681\r
682 @param Handle Debug port handle.\r
683 @param Buffer Pointer to the data buffer to store the data read from the debug device.\r
684 @param NumberOfBytes Number of bytes which will be read.\r
685 @param Timeout Timeout value for reading from debug device. It unit is Microsecond.\r
686\r
687 @retval 0 Read data failed, no data is to be read.\r
688 @retval >0 Actual number of bytes read from debug device.\r
689\r
690**/\r
691UINTN\r
692EFIAPI\r
693DebugPortReadBuffer (\r
694 IN DEBUG_PORT_HANDLE Handle,\r
695 IN UINT8 *Buffer,\r
696 IN UINTN NumberOfBytes,\r
697 IN UINTN Timeout\r
698 )\r
699{\r
700 USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
701 USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
702 RETURN_STATUS Status;\r
703 UINT8 Received;\r
704 UINTN Total;\r
705 UINTN Remaining;\r
706 UINT8 Index;\r
707 UINT8 Length;\r
708\r
709 if (NumberOfBytes == 0 || Buffer == NULL) {\r
710 return 0;\r
711 }\r
712\r
713 Received = 0;\r
714 Total = 0;\r
715 Remaining = 0;\r
716\r
717 //\r
718 // If Handle is NULL, it means memory is ready for use.\r
719 // Use global variable to store handle value.\r
720 //\r
721 if (Handle == NULL) {\r
722 UsbDebugPortHandle = &mUsbDebugPortHandle;\r
723 } else {\r
724 UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;\r
725 }\r
726\r
e2104834 727 //\r
728 // Check if debug port is ready\r
729 //\r
730 if (!UsbDebugPortHandle->Initialized) {\r
731 return 0;\r
732 }\r
733\r
18b144ea 734 if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
735 Status = InitializeUsbDebugHardware (UsbDebugPortHandle);\r
736 if (RETURN_ERROR(Status)) {\r
737 return 0;\r
738 }\r
739 }\r
740\r
741 UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
742\r
743 //\r
744 // First read data from buffer, then read debug port hw to get received data.\r
745 //\r
746 if (UsbDebugPortHandle->DataCount > 0) {\r
747 if (NumberOfBytes <= UsbDebugPortHandle->DataCount) {\r
748 Total = NumberOfBytes;\r
749 } else {\r
750 Total = UsbDebugPortHandle->DataCount;\r
751 }\r
752\r
753 for (Index = 0; Index < Total; Index++) {\r
754 Buffer[Index] = UsbDebugPortHandle->Data[Index];\r
755 }\r
756\r
757 for (Index = 0; Index < UsbDebugPortHandle->DataCount - Total; Index++) {\r
758 if (Total + Index >= 8) {\r
759 return 0;\r
760 }\r
761 UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Total + Index];\r
762 }\r
763 UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - (UINT8)Total);\r
764 }\r
765\r
766 //\r
767 // If Timeout is equal to 0, then it means it should always wait until all datum required are received.\r
768 //\r
769 if (Timeout == 0) {\r
770 Timeout = 0xFFFFFFFF;\r
771 }\r
772\r
773 //\r
774 // Read remaining data by executing one or more usb debug transfer transactions at usb debug port hw.\r
775 //\r
776 while ((Total < NumberOfBytes) && (Timeout != 0)) {\r
777 Remaining = NumberOfBytes - Total;\r
778 if (Remaining >= USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
779 Status = UsbDebugPortIn(UsbDebugPortRegister, Buffer + Total, &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle);\r
780\r
781 if (RETURN_ERROR(Status)) {\r
782 return Total;\r
783 }\r
784 } else {\r
785 Status = UsbDebugPortIn(UsbDebugPortRegister, &UsbDebugPortHandle->Data[0], &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle);\r
786\r
787 if (RETURN_ERROR(Status)) {\r
788 return Total;\r
789 }\r
790\r
791 UsbDebugPortHandle->DataCount = Received;\r
792\r
793 if (Remaining <= Received) {\r
794 Length = (UINT8)Remaining;\r
795 } else {\r
796 Length = (UINT8)Received;\r
797 }\r
798\r
799 //\r
800 // Copy required data from the data buffer to user buffer.\r
801 //\r
802 for (Index = 0; Index < Length; Index++) {\r
803 (Buffer + Total)[Index] = UsbDebugPortHandle->Data[Index];\r
804 UsbDebugPortHandle->DataCount--;\r
805 }\r
806\r
807 //\r
808 // reorder the data buffer to make available data arranged from the beginning of the data buffer.\r
809 //\r
810 for (Index = 0; Index < Received - Length; Index++) {\r
811 if (Length + Index >= 8) {\r
812 return 0;\r
813 }\r
814 UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Length + Index];\r
815 }\r
816 //\r
817 // fixup the real received length in Buffer.\r
818 //\r
819 Received = Length;\r
820 }\r
821 UsbDebugPortHandle->BulkInToggle ^= 1;\r
822\r
823 Total += Received;\r
824 Timeout -= 100;\r
825 }\r
826\r
827 return Total;\r
828}\r
829\r
830/**\r
831 Write data from buffer to debug device.\r
832\r
833 Writes NumberOfBytes data bytes from Buffer to the debug device.\r
834 The number of bytes actually written to the debug device is returned.\r
835 If the return value is less than NumberOfBytes, then the write operation failed.\r
836 If NumberOfBytes is zero, then return 0.\r
837\r
838 @param Handle Debug port handle.\r
839 @param Buffer Pointer to the data buffer to be written.\r
840 @param NumberOfBytes Number of bytes to written to the debug device.\r
841\r
842 @retval 0 NumberOfBytes is 0.\r
843 @retval >0 The number of bytes written to the debug device.\r
844 If this value is less than NumberOfBytes, then the read operation failed.\r
845\r
846**/\r
847UINTN\r
848EFIAPI\r
849DebugPortWriteBuffer (\r
850 IN DEBUG_PORT_HANDLE Handle,\r
851 IN UINT8 *Buffer,\r
852 IN UINTN NumberOfBytes\r
853 )\r
854{\r
855 USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
856 USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
857 RETURN_STATUS Status;\r
858 UINT8 Sent;\r
859 UINTN Total;\r
860 UINT8 ReceivedPid;\r
861\r
862 if (NumberOfBytes == 0 || Buffer == NULL) {\r
863 return 0;\r
864 }\r
865\r
866 Sent = 0;\r
867 Total = 0;\r
868\r
869 //\r
870 // If Handle is NULL, it means memory is ready for use.\r
871 // Use global variable to store handle value.\r
872 //\r
873 if (Handle == NULL) {\r
874 UsbDebugPortHandle = &mUsbDebugPortHandle;\r
875 } else {\r
876 UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;\r
877 }\r
878\r
e2104834 879 //\r
880 // Check if debug port is ready\r
881 //\r
882 if (!UsbDebugPortHandle->Initialized) {\r
883 return 0;\r
884 }\r
885\r
18b144ea 886 if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
887 Status = InitializeUsbDebugHardware (UsbDebugPortHandle);\r
888 if (RETURN_ERROR(Status)) {\r
889 return 0;\r
890 }\r
891 }\r
892\r
893 UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
894\r
895 while ((Total < NumberOfBytes)) {\r
896 if (NumberOfBytes - Total > USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
897 Sent = USB_DEBUG_PORT_MAX_PACKET_SIZE;\r
898 } else {\r
899 Sent = (UINT8)(NumberOfBytes - Total);\r
900 }\r
901\r
902 Status = UsbDebugPortOut(UsbDebugPortRegister, Buffer + Total, Sent, OUTPUT_PID, 0x7F, 0x01, UsbDebugPortHandle->BulkOutToggle);\r
903\r
904 if (RETURN_ERROR(Status)) {\r
905 return Total;\r
906 }\r
907\r
908 ReceivedPid = (MmioRead8((UINTN)&UsbDebugPortRegister->ReceivedPid));\r
909 //\r
910 // If received a NAK_PID on write transaction, it means the usb debug device is busy and can not handle this transaction.\r
911 // should send the packet again.\r
912 //\r
913 if (ReceivedPid == NAK_PID) {\r
914 Sent = 0;\r
915 } else {\r
916 UsbDebugPortHandle->BulkOutToggle ^= 1;\r
917 }\r
918 Total += Sent;\r
919 }\r
920 return Total;\r
921}\r
922\r
923/**\r
924 Polls a debug device to see if there is any data waiting to be read.\r
925\r
926 Polls a debug device to see if there is any data waiting to be read.\r
927 If there is data waiting to be read from the debug device, then TRUE is returned.\r
928 If there is no data waiting to be read from the debug device, then FALSE is returned.\r
929\r
930 @param Handle Debug port handle.\r
931\r
932 @retval TRUE Data is waiting to be read from the debug device.\r
933 @retval FALSE There is no data waiting to be read from the serial device.\r
934\r
935**/\r
936BOOLEAN\r
937EFIAPI\r
938DebugPortPollBuffer (\r
939 IN DEBUG_PORT_HANDLE Handle\r
940 )\r
941{\r
942 USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
943 USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
944 UINT8 Length;\r
945 UINT8 Index;\r
946 RETURN_STATUS Status;\r
947\r
948 //\r
949 // If Handle is NULL, it means memory is ready for use.\r
950 // Use global variable to store handle value.\r
951 //\r
952 if (Handle == NULL) {\r
953 UsbDebugPortHandle = &mUsbDebugPortHandle;\r
954 } else {\r
955 UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;\r
956 }\r
957\r
e2104834 958 //\r
959 // Check if debug port is ready\r
960 //\r
961 if (!UsbDebugPortHandle->Initialized) {\r
962 return 0;\r
963 }\r
964\r
18b144ea 965 if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
966 Status = InitializeUsbDebugHardware(UsbDebugPortHandle);\r
967 if (RETURN_ERROR(Status)) {\r
968 return FALSE;\r
969 }\r
970 }\r
971\r
972 //\r
973 // If the data buffer is not empty, then return TRUE directly.\r
974 // else initialize a usb read transaction and read data to the data buffer.\r
975 //\r
976 if (UsbDebugPortHandle->DataCount != 0) {\r
977 return TRUE;\r
978 }\r
979\r
980 UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);\r
981\r
982 UsbDebugPortRegister->TokenPid = INPUT_PID;\r
983 if (UsbDebugPortHandle->BulkInToggle == 0) {\r
984 UsbDebugPortRegister->SendPid = DATA0_PID;\r
985 } else {\r
986 UsbDebugPortRegister->SendPid = DATA1_PID;\r
987 }\r
988 UsbDebugPortRegister->UsbAddress = 0x7F;\r
989 UsbDebugPortRegister->UsbEndPoint = 0x82 & 0x0F;\r
990\r
991 //\r
992 // Clearing W/R bit to indicate it's a READ operation\r
993 //\r
994 MmioAnd32((UINTN)&UsbDebugPortRegister->ControlStatus, (UINT32)~BIT4);\r
995 //\r
996 // Setting GO bit as well as clearing DONE bit\r
997 //\r
998 MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, (UINT32)BIT5);\r
999\r
1000 //\r
1001 // Wait for completing the request\r
1002 //\r
1003 while ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (UINT32)BIT16) == 0);\r
1004\r
1005 if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus)) & BIT6) {\r
1006 return FALSE;\r
1007 }\r
1008\r
1009 Length = (UINT8)(MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & 0xF);\r
1010\r
1011 if (Length > 8) {\r
1012 return FALSE;\r
1013 }\r
1014\r
1015 UsbDebugPortHandle->BulkInToggle ^= 1;\r
1016\r
1017 if (Length == 0) {\r
1018 return FALSE;\r
1019 }\r
1020\r
1021 for (Index = 0; Index < Length; Index++) {\r
1022 UsbDebugPortHandle->Data[Index] = UsbDebugPortRegister->DataBuffer[Index];\r
1023 }\r
1024 UsbDebugPortHandle->DataCount = Length;\r
1025\r
1026 return TRUE;\r
1027}\r
1028\r
1029/**\r
1030 Initialize the debug port.\r
1031\r
1032 If Function is not NULL, Debug Communication Libary will call this function\r
1033 by passing in the Context to be the first parameter. If needed, Debug Communication\r
1034 Library will create one debug port handle to be the second argument passing in\r
1035 calling the Function, otherwise it will pass NULL to be the second argument of\r
1036 Function.\r
1037\r
1038 If Function is NULL, and Context is not NULL, the Debug Communication Library could\r
1039 a) Return the same handle as passed in (as Context parameter).\r
1040 b) Ignore the input Context parameter and create new hanlde to be returned.\r
1041\r
1042 If parameter Function is NULL and Context is NULL, Debug Communication Library could\r
1043 created a new handle if needed and return it, otherwise it will return NULL.\r
1044\r
1045 @param[in] Context Context needed by callback function; it was optional.\r
1046 @param[in] Function Continue function called by Debug Communication library;\r
1047 it was optional.\r
1048\r
1049 @return The debug port handle created by Debug Communication Library if Function\r
1050 is not NULL.\r
1051\r
1052**/\r
1053DEBUG_PORT_HANDLE\r
1054EFIAPI\r
1055DebugPortInitialize (\r
1056 IN VOID *Context,\r
1057 IN DEBUG_PORT_CONTINUE Function\r
1058 )\r
1059{\r
1060 RETURN_STATUS Status;\r
1061 USB_DEBUG_PORT_HANDLE Handle;\r
1062\r
1063 if (Function == NULL && Context != NULL) {\r
1064 return (DEBUG_PORT_HANDLE *) Context;\r
1065 }\r
1066\r
1067 ZeroMem(&Handle, sizeof (USB_DEBUG_PORT_HANDLE));\r
1068\r
1069 Status = CalculateUsbDebugPortBar(&Handle.DebugPortOffset, &Handle.DebugPortBarNumber);\r
1070 if (RETURN_ERROR (Status)) {\r
e2104834 1071 DEBUG ((EFI_D_ERROR, "USB Debug Port: EHCI host controller does not support debug port capability!\n"));\r
1072 goto Exit;\r
18b144ea 1073 }\r
1074\r
1075 Handle.EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);\r
1076\r
1077 if (Handle.EhciMemoryBase == 0) {\r
1078 //\r
1079 // Usb Debug Port MMIO Space Is Not Enabled. Assumption here that DebugPortBase is zero\r
1080 //\r
1081 PciWrite32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET, PcdGet32(PcdUsbEhciMemorySpaceBase));\r
1082 Handle.EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);\r
1083 }\r
1084\r
1085 Handle.UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4);\r
1086\r
1087 if (Handle.UsbDebugPortMemoryBase == 0) {\r
1088 //\r
1089 // Usb Debug Port MMIO Space Is Not Enabled. Assumption here that DebugPortBase is zero\r
1090 //\r
1091 PciWrite32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4, PcdGet32(PcdUsbDebugPortMemorySpaceBase));\r
1092 Handle.UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4);\r
1093 }\r
1094\r
1095 Status = InitializeUsbDebugHardware (&Handle);\r
1096 if (RETURN_ERROR(Status)) {\r
e2104834 1097 DEBUG ((EFI_D_ERROR, "USB Debug Port: Initialization failed, please check if USB debug cable is plugged into EHCI debug port correctly!\n"));\r
1098 goto Exit;\r
18b144ea 1099 }\r
1100\r
e2104834 1101 //\r
1102 // Set debug port initialized successfully flag\r
1103 //\r
1104 Handle.Initialized = TRUE;\r
1105\r
1106Exit:\r
1107\r
18b144ea 1108 if (Function != NULL) {\r
1109 Function (Context, &Handle);\r
1110 } else {\r
1111 CopyMem(&mUsbDebugPortHandle, &Handle, sizeof (USB_DEBUG_PORT_HANDLE));\r
1112 }\r
1113\r
1114 return (DEBUG_PORT_HANDLE)(UINTN)&mUsbDebugPortHandle;\r
1115}\r
1116\r