]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c
StdLib: Fix compilation errors caused by previous commit of daConsole.c
[mirror_edk2.git] / MdeModulePkg / Library / BaseSerialPortLib16550 / BaseSerialPortLib16550.c
CommitLineData
467d15ae 1/** @file\r
2 16550 UART Serial Port library functions\r
3\r
35f910f0 4 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
cd68e4a8 5 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
467d15ae 6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include <Base.h>\r
31122d8c 17#include <IndustryStandard/Pci.h>\r
467d15ae 18#include <Library/SerialPortLib.h>\r
19#include <Library/PcdLib.h>\r
20#include <Library/IoLib.h>\r
31122d8c 21#include <Library/PciLib.h>\r
467d15ae 22#include <Library/PlatformHookLib.h>\r
31122d8c
LG
23#include <Library/BaseLib.h>\r
24\r
25//\r
26// PCI Defintions.\r
27//\r
28#define PCI_BRIDGE_32_BIT_IO_SPACE 0x01\r
467d15ae 29\r
30//\r
31// 16550 UART register offsets and bitfields\r
32//\r
33#define R_UART_RXBUF 0\r
34#define R_UART_TXBUF 0\r
35#define R_UART_BAUD_LOW 0\r
36#define R_UART_BAUD_HIGH 1\r
37#define R_UART_FCR 2\r
38#define B_UART_FCR_FIFOE BIT0\r
39#define B_UART_FCR_FIFO64 BIT5\r
40#define R_UART_LCR 3\r
41#define B_UART_LCR_DLAB BIT7\r
42#define R_UART_MCR 4\r
c0e6c393 43#define B_UART_MCR_DTRC BIT0\r
467d15ae 44#define B_UART_MCR_RTS BIT1\r
45#define R_UART_LSR 5\r
46#define B_UART_LSR_RXRDY BIT0\r
47#define B_UART_LSR_TXRDY BIT5\r
48#define B_UART_LSR_TEMT BIT6\r
49#define R_UART_MSR 6\r
50#define B_UART_MSR_CTS BIT4\r
784ce127 51#define B_UART_MSR_DSR BIT5\r
c0e6c393
SZ
52#define B_UART_MSR_RI BIT6\r
53#define B_UART_MSR_DCD BIT7\r
467d15ae 54\r
31122d8c
LG
55//\r
56// 4-byte structure for each PCI node in PcdSerialPciDeviceInfo\r
57//\r
58typedef struct {\r
59 UINT8 Device;\r
60 UINT8 Function;\r
61 UINT16 PowerManagementStatusAndControlRegister;\r
62} PCI_UART_DEVICE_INFO;\r
63\r
467d15ae 64/**\r
65 Read an 8-bit 16550 register. If PcdSerialUseMmio is TRUE, then the value is read from \r
66 MMIO space. If PcdSerialUseMmio is FALSE, then the value is read from I/O space. The\r
67 parameter Offset is added to the base address of the 16550 registers that is specified \r
68 by PcdSerialRegisterBase. \r
69 \r
74a6d860 70 @param Base The base address register of UART device.\r
467d15ae 71 @param Offset The offset of the 16550 register to read.\r
72\r
73 @return The value read from the 16550 register.\r
74\r
75**/\r
76UINT8\r
77SerialPortReadRegister (\r
31122d8c 78 UINTN Base,\r
467d15ae 79 UINTN Offset\r
80 )\r
81{\r
82 if (PcdGetBool (PcdSerialUseMmio)) {\r
cd68e4a8 83 return MmioRead8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride));\r
467d15ae 84 } else {\r
cd68e4a8 85 return IoRead8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride));\r
467d15ae 86 }\r
87}\r
88\r
89/**\r
90 Write an 8-bit 16550 register. If PcdSerialUseMmio is TRUE, then the value is written to\r
91 MMIO space. If PcdSerialUseMmio is FALSE, then the value is written to I/O space. The\r
92 parameter Offset is added to the base address of the 16550 registers that is specified \r
93 by PcdSerialRegisterBase. \r
94 \r
74a6d860 95 @param Base The base address register of UART device.\r
e25fb2c0 96 @param Offset The offset of the 16550 register to write.\r
97 @param Value The value to write to the 16550 register specified by Offset.\r
467d15ae 98\r
99 @return The value written to the 16550 register.\r
100\r
101**/\r
102UINT8\r
103SerialPortWriteRegister (\r
31122d8c 104 UINTN Base,\r
467d15ae 105 UINTN Offset,\r
106 UINT8 Value\r
107 )\r
108{\r
109 if (PcdGetBool (PcdSerialUseMmio)) {\r
cd68e4a8 110 return MmioWrite8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride), Value);\r
467d15ae 111 } else {\r
cd68e4a8 112 return IoWrite8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride), Value);\r
467d15ae 113 }\r
114}\r
115\r
31122d8c
LG
116/**\r
117 Update the value of an 16-bit PCI configuration register in a PCI device. If the \r
118 PCI Configuration register specified by PciAddress is already programmed with a \r
119 non-zero value, then return the current value. Otherwise update the PCI configuration \r
120 register specified by PciAddress with the value specified by Value and return the\r
121 value programmed into the PCI configuration register. All values must be masked \r
122 using the bitmask specified by Mask.\r
123\r
124 @param PciAddress PCI Library address of the PCI Configuration register to update.\r
125 @param Value The value to program into the PCI Configuration Register.\r
126 @param Mask Bitmask of the bits to check and update in the PCI configuration register.\r
127\r
128**/\r
129UINT16\r
130SerialPortLibUpdatePciRegister16 (\r
131 UINTN PciAddress,\r
132 UINT16 Value,\r
133 UINT16 Mask\r
134 )\r
135{\r
136 UINT16 CurrentValue;\r
137 \r
138 CurrentValue = PciRead16 (PciAddress) & Mask;\r
139 if (CurrentValue != 0) {\r
140 return CurrentValue;\r
141 }\r
142 return PciWrite16 (PciAddress, Value & Mask);\r
143}\r
144\r
145/**\r
146 Update the value of an 32-bit PCI configuration register in a PCI device. If the \r
147 PCI Configuration register specified by PciAddress is already programmed with a \r
148 non-zero value, then return the current value. Otherwise update the PCI configuration \r
149 register specified by PciAddress with the value specified by Value and return the\r
150 value programmed into the PCI configuration register. All values must be masked \r
151 using the bitmask specified by Mask.\r
152\r
153 @param PciAddress PCI Library address of the PCI Configuration register to update.\r
154 @param Value The value to program into the PCI Configuration Register.\r
155 @param Mask Bitmask of the bits to check and update in the PCI configuration register.\r
156\r
157 @return The Secondary bus number that is actually programed into the PCI to PCI Bridge device.\r
158\r
159**/\r
160UINT32\r
161SerialPortLibUpdatePciRegister32 (\r
162 UINTN PciAddress,\r
163 UINT32 Value,\r
164 UINT32 Mask\r
165 )\r
166{\r
167 UINT32 CurrentValue;\r
168 \r
169 CurrentValue = PciRead32 (PciAddress) & Mask;\r
170 if (CurrentValue != 0) {\r
171 return CurrentValue;\r
172 }\r
173 return PciWrite32 (PciAddress, Value & Mask);\r
174}\r
175\r
176/**\r
177 Retrieve the I/O or MMIO base address register for the PCI UART device. \r
178 \r
179 This function assumes Root Bus Numer is Zero, and enables I/O and MMIO in PCI UART \r
180 Device if they are not already enabled. \r
181 \r
74a6d860 182 @return The base address register of the UART device.\r
31122d8c
LG
183\r
184**/\r
185UINTN\r
186GetSerialRegisterBase (\r
187 VOID\r
188 )\r
189{\r
190 UINTN PciLibAddress;\r
31122d8c
LG
191 UINTN BusNumber;\r
192 UINTN SubordinateBusNumber;\r
193 UINT32 ParentIoBase;\r
194 UINT32 ParentIoLimit;\r
195 UINT16 ParentMemoryBase;\r
196 UINT16 ParentMemoryLimit;\r
197 UINT32 IoBase;\r
198 UINT32 IoLimit;\r
199 UINT16 MemoryBase;\r
200 UINT16 MemoryLimit;\r
201 UINTN SerialRegisterBase;\r
202 UINTN BarIndex;\r
203 UINT32 RegisterBaseMask;\r
204 PCI_UART_DEVICE_INFO *DeviceInfo;\r
205\r
206 //\r
207 // Get PCI Device Info\r
208 //\r
209 DeviceInfo = (PCI_UART_DEVICE_INFO *) PcdGetPtr (PcdSerialPciDeviceInfo);\r
210 \r
211 //\r
212 // If PCI Device Info is empty, then assume fixed address UART and return PcdSerialRegisterBase\r
213 // \r
214 if (DeviceInfo->Device == 0xff) {\r
215 return (UINTN)PcdGet64 (PcdSerialRegisterBase);\r
216 }\r
217\r
218 //\r
219 // Assume PCI Bus 0 I/O window is 0-64KB and MMIO windows is 0-4GB\r
220 //\r
221 ParentMemoryBase = 0 >> 16;\r
222 ParentMemoryLimit = 0xfff00000 >> 16;\r
223 ParentIoBase = 0 >> 12;\r
224 ParentIoLimit = 0xf000 >> 12;\r
225 \r
226 //\r
227 // Enable I/O and MMIO in PCI Bridge\r
228 // Assume Root Bus Numer is Zero. \r
229 //\r
230 for (BusNumber = 0; (DeviceInfo + 1)->Device != 0xff; DeviceInfo++) {\r
231 //\r
232 // Compute PCI Lib Address to PCI to PCI Bridge\r
233 //\r
234 PciLibAddress = PCI_LIB_ADDRESS (BusNumber, DeviceInfo->Device, DeviceInfo->Function, 0);\r
235 \r
236 //\r
237 // Retrieve and verify the bus numbers in the PCI to PCI Bridge\r
238 //\r
31122d8c
LG
239 BusNumber = PciRead8 (PciLibAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);\r
240 SubordinateBusNumber = PciRead8 (PciLibAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
241 if (BusNumber == 0 || BusNumber > SubordinateBusNumber) {\r
242 return 0;\r
243 }\r
244\r
245 //\r
246 // Retrieve and verify the I/O or MMIO decode window in the PCI to PCI Bridge\r
247 //\r
248 if (PcdGetBool (PcdSerialUseMmio)) {\r
c9e0bba3
LG
249 MemoryLimit = PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit)) & 0xfff0;\r
250 MemoryBase = PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase)) & 0xfff0;\r
31122d8c
LG
251\r
252 //\r
253 // If PCI Bridge MMIO window is disabled, then return 0\r
254 //\r
255 if (MemoryLimit < MemoryBase) {\r
256 return 0;\r
257 }\r
258 \r
259 //\r
260 // If PCI Bridge MMIO window is not in the address range decoded by the parent PCI Bridge, then return 0\r
261 // \r
262 if (MemoryBase < ParentMemoryBase || MemoryBase > ParentMemoryLimit || MemoryLimit > ParentMemoryLimit) {\r
263 return 0;\r
264 }\r
265 ParentMemoryBase = MemoryBase;\r
266 ParentMemoryLimit = MemoryLimit;\r
267 } else {\r
c9e0bba3 268 IoLimit = PciRead8 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit));\r
31122d8c
LG
269 if ((IoLimit & PCI_BRIDGE_32_BIT_IO_SPACE ) == 0) {\r
270 IoLimit = IoLimit >> 4;\r
271 } else {\r
c9e0bba3 272 IoLimit = (PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimitUpper16)) << 4) | (IoLimit >> 4);\r
31122d8c 273 }\r
c9e0bba3 274 IoBase = PciRead8 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase));\r
31122d8c
LG
275 if ((IoBase & PCI_BRIDGE_32_BIT_IO_SPACE ) == 0) {\r
276 IoBase = IoBase >> 4;\r
277 } else {\r
c9e0bba3 278 IoBase = (PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBaseUpper16)) << 4) | (IoBase >> 4);\r
31122d8c
LG
279 }\r
280 \r
281 //\r
282 // If PCI Bridge I/O window is disabled, then return 0\r
283 //\r
284 if (IoLimit < IoBase) {\r
285 return 0;\r
286 }\r
287 \r
288 //\r
289 // If PCI Bridge I/O window is not in the address range decoded by the parent PCI Bridge, then return 0\r
290 // \r
291 if (IoBase < ParentIoBase || IoBase > ParentIoLimit || IoLimit > ParentIoLimit) {\r
292 return 0;\r
293 }\r
294 ParentIoBase = IoBase;\r
295 ParentIoLimit = IoLimit;\r
296 }\r
297 }\r
298\r
299 //\r
300 // Compute PCI Lib Address to PCI UART\r
301 //\r
302 PciLibAddress = PCI_LIB_ADDRESS (BusNumber, DeviceInfo->Device, DeviceInfo->Function, 0);\r
303 \r
304 //\r
305 // Find the first IO or MMIO BAR\r
306 //\r
307 RegisterBaseMask = 0xFFFFFFF0;\r
308 for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex ++) {\r
309 SerialRegisterBase = PciRead32 (PciLibAddress + PCI_BASE_ADDRESSREG_OFFSET + BarIndex * 4);\r
310 if (PcdGetBool (PcdSerialUseMmio) && ((SerialRegisterBase & BIT0) == 0)) {\r
311 //\r
312 // MMIO BAR is found\r
313 //\r
314 RegisterBaseMask = 0xFFFFFFF0;\r
315 break;\r
316 }\r
317\r
318 if ((!PcdGetBool (PcdSerialUseMmio)) && ((SerialRegisterBase & BIT0) != 0)) {\r
319 //\r
320 // IO BAR is found\r
321 //\r
322 RegisterBaseMask = 0xFFFFFFF8;\r
323 break;\r
324 }\r
325 }\r
326\r
327 //\r
328 // MMIO or IO BAR is not found.\r
329 //\r
330 if (BarIndex == PCI_MAX_BAR) {\r
331 return 0;\r
332 }\r
333\r
334 //\r
335 // Program UART BAR\r
336 // \r
337 SerialRegisterBase = SerialPortLibUpdatePciRegister32 (\r
338 PciLibAddress + PCI_BASE_ADDRESSREG_OFFSET + BarIndex * 4,\r
339 (UINT32)PcdGet64 (PcdSerialRegisterBase), \r
340 RegisterBaseMask\r
341 );\r
342\r
343 //\r
344 // Verify that the UART BAR is in the address range decoded by the parent PCI Bridge\r
345 // \r
346 if (PcdGetBool (PcdSerialUseMmio)) {\r
347 if (((SerialRegisterBase >> 16) & 0xfff0) < ParentMemoryBase || ((SerialRegisterBase >> 16) & 0xfff0) > ParentMemoryLimit) {\r
348 return 0;\r
349 }\r
350 } else {\r
351 if ((SerialRegisterBase >> 12) < ParentIoBase || (SerialRegisterBase >> 12) > ParentIoLimit) {\r
352 return 0;\r
353 }\r
354 }\r
355 \r
356 //\r
357 // Enable I/O and MMIO in PCI UART Device if they are not already enabled\r
358 //\r
359 PciOr16 (\r
360 PciLibAddress + PCI_COMMAND_OFFSET,\r
361 PcdGetBool (PcdSerialUseMmio) ? EFI_PCI_COMMAND_MEMORY_SPACE : EFI_PCI_COMMAND_IO_SPACE\r
362 );\r
363\r
364 //\r
365 // Force D0 state if a Power Management and Status Register is specified\r
366 //\r
367 if (DeviceInfo->PowerManagementStatusAndControlRegister != 0x00) {\r
368 if ((PciRead16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister) & (BIT0 | BIT1)) != 0x00) {\r
369 PciAnd16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister, (UINT16)~(BIT0 | BIT1));\r
370 //\r
371 // If PCI UART was not in D0, then make sure FIFOs are enabled, but do not reset FIFOs\r
372 //\r
373 SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)));\r
374 }\r
375 }\r
376 \r
377 //\r
378 // Get PCI Device Info\r
379 //\r
380 DeviceInfo = (PCI_UART_DEVICE_INFO *) PcdGetPtr (PcdSerialPciDeviceInfo);\r
381\r
382 //\r
383 // Enable I/O or MMIO in PCI Bridge\r
384 // Assume Root Bus Numer is Zero. \r
385 //\r
386 for (BusNumber = 0; (DeviceInfo + 1)->Device != 0xff; DeviceInfo++) {\r
387 //\r
388 // Compute PCI Lib Address to PCI to PCI Bridge\r
389 //\r
390 PciLibAddress = PCI_LIB_ADDRESS (BusNumber, DeviceInfo->Device, DeviceInfo->Function, 0);\r
391 \r
392 //\r
393 // Enable the I/O or MMIO decode windows in the PCI to PCI Bridge\r
394 //\r
395 PciOr16 (\r
396 PciLibAddress + PCI_COMMAND_OFFSET, \r
397 PcdGetBool (PcdSerialUseMmio) ? EFI_PCI_COMMAND_MEMORY_SPACE : EFI_PCI_COMMAND_IO_SPACE\r
398 );\r
399 \r
400 //\r
401 // Force D0 state if a Power Management and Status Register is specified\r
402 //\r
403 if (DeviceInfo->PowerManagementStatusAndControlRegister != 0x00) {\r
404 if ((PciRead16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister) & (BIT0 | BIT1)) != 0x00) {\r
405 PciAnd16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister, (UINT16)~(BIT0 | BIT1));\r
406 }\r
407 }\r
408 \r
409 BusNumber = PciRead8 (PciLibAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);\r
410 }\r
411 \r
412 return SerialRegisterBase;\r
413}\r
414\r
e5010d30
RN
415/**\r
416 Return whether the hardware flow control signal allows writing.\r
417\r
74a6d860
LG
418 @param SerialRegisterBase The base address register of UART device.\r
419\r
e5010d30
RN
420 @retval TRUE The serial port is writable.\r
421 @retval FALSE The serial port is not writable.\r
422**/\r
423BOOLEAN\r
424SerialPortWritable (\r
31122d8c 425 UINTN SerialRegisterBase\r
e5010d30
RN
426 )\r
427{\r
428 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {\r
429 if (PcdGetBool (PcdSerialDetectCable)) {\r
430 //\r
431 // Wait for both DSR and CTS to be set\r
432 // DSR is set if a cable is connected.\r
433 // CTS is set if it is ok to transmit data\r
434 //\r
435 // DSR CTS Description Action\r
436 // === === ======================================== ========\r
437 // 0 0 No cable connected. Wait\r
438 // 0 1 No cable connected. Wait\r
439 // 1 0 Cable connected, but not clear to send. Wait\r
440 // 1 1 Cable connected, and clear to send. Transmit\r
441 //\r
31122d8c 442 return (BOOLEAN) ((SerialPortReadRegister (SerialRegisterBase, R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) == (B_UART_MSR_DSR | B_UART_MSR_CTS));\r
e5010d30
RN
443 } else {\r
444 //\r
445 // Wait for both DSR and CTS to be set OR for DSR to be clear. \r
446 // DSR is set if a cable is connected.\r
447 // CTS is set if it is ok to transmit data\r
448 //\r
449 // DSR CTS Description Action\r
450 // === === ======================================== ========\r
451 // 0 0 No cable connected. Transmit\r
452 // 0 1 No cable connected. Transmit\r
453 // 1 0 Cable connected, but not clear to send. Wait\r
454 // 1 1 Cable connected, and clar to send. Transmit\r
455 //\r
31122d8c 456 return (BOOLEAN) ((SerialPortReadRegister (SerialRegisterBase, R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) != (B_UART_MSR_DSR));\r
e5010d30
RN
457 }\r
458 }\r
459\r
460 return TRUE;\r
461}\r
462\r
467d15ae 463/**\r
464 Initialize the serial device hardware.\r
465 \r
466 If no initialization is required, then return RETURN_SUCCESS.\r
e5010d30 467 If the serial device was successfully initialized, then return RETURN_SUCCESS.\r
467d15ae 468 If the serial device could not be initialized, then return RETURN_DEVICE_ERROR.\r
469 \r
470 @retval RETURN_SUCCESS The serial device was initialized.\r
471 @retval RETURN_DEVICE_ERROR The serial device could not be initialized.\r
472\r
473**/\r
474RETURN_STATUS\r
475EFIAPI\r
476SerialPortInitialize (\r
477 VOID\r
478 )\r
479{\r
480 RETURN_STATUS Status;\r
31122d8c
LG
481 UINTN SerialRegisterBase;\r
482 UINT32 Divisor;\r
483 UINT32 CurrentDivisor; \r
467d15ae 484 BOOLEAN Initialized;\r
485\r
486 //\r
487 // Perform platform specific initialization required to enable use of the 16550 device\r
488 // at the location specified by PcdSerialUseMmio and PcdSerialRegisterBase.\r
489 //\r
490 Status = PlatformHookSerialPortInitialize ();\r
491 if (RETURN_ERROR (Status)) {\r
492 return Status;\r
493 }\r
494\r
31122d8c
LG
495 //\r
496 // Calculate divisor for baud generator\r
497 // Ref_Clk_Rate / Baud_Rate / 16\r
498 //\r
499 Divisor = PcdGet32 (PcdSerialClockRate) / (PcdGet32 (PcdSerialBaudRate) * 16);\r
500 if ((PcdGet32 (PcdSerialClockRate) % (PcdGet32 (PcdSerialBaudRate) * 16)) >= PcdGet32 (PcdSerialBaudRate) * 8) {\r
501 Divisor++;\r
502 }\r
503\r
504 //\r
505 // Get the base address of the serial port in either I/O or MMIO space\r
506 //\r
507 SerialRegisterBase = GetSerialRegisterBase ();\r
508 if (SerialRegisterBase ==0) {\r
509 return RETURN_DEVICE_ERROR;\r
510 }\r
511\r
467d15ae 512 //\r
513 // See if the serial port is already initialized\r
514 //\r
515 Initialized = TRUE;\r
31122d8c 516 if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) & 0x3F) != (PcdGet8 (PcdSerialLineControl) & 0x3F)) {\r
467d15ae 517 Initialized = FALSE;\r
518 }\r
31122d8c
LG
519 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) | B_UART_LCR_DLAB));\r
520 CurrentDivisor = SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_HIGH) << 8;\r
521 CurrentDivisor |= (UINT32) SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_LOW);\r
522 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) & ~B_UART_LCR_DLAB));\r
523 if (CurrentDivisor != Divisor) {\r
467d15ae 524 Initialized = FALSE;\r
525 }\r
526 if (Initialized) {\r
527 return RETURN_SUCCESS;\r
528 }\r
31122d8c
LG
529\r
530 //\r
531 // Wait for the serial port to be ready.\r
532 // Verify that both the transmit FIFO and the shift register are empty.\r
533 //\r
534 while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY));\r
467d15ae 535 \r
536 //\r
537 // Configure baud rate\r
538 //\r
31122d8c
LG
539 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB);\r
540 SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8) (Divisor >> 8));\r
541 SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8) (Divisor & 0xff));\r
467d15ae 542\r
543 //\r
544 // Clear DLAB and configure Data Bits, Parity, and Stop Bits.\r
545 // Strip reserved bits from PcdSerialLineControl\r
546 //\r
31122d8c 547 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3F));\r
467d15ae 548\r
549 //\r
550 // Enable and reset FIFOs\r
551 // Strip reserved bits from PcdSerialFifoControl\r
552 //\r
31122d8c
LG
553 SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, 0x00);\r
554 SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)));\r
467d15ae 555\r
556 //\r
557 // Put Modem Control Register(MCR) into its reset state of 0x00.\r
558 // \r
31122d8c
LG
559 SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, 0x00);\r
560\r
467d15ae 561 return RETURN_SUCCESS;\r
562}\r
563\r
564/**\r
565 Write data from buffer to serial device. \r
31122d8c 566\r
467d15ae 567 Writes NumberOfBytes data bytes from Buffer to the serial device. \r
568 The number of bytes actually written to the serial device is returned.\r
569 If the return value is less than NumberOfBytes, then the write operation failed.\r
570\r
571 If Buffer is NULL, then ASSERT(). \r
572\r
573 If NumberOfBytes is zero, then return 0.\r
574\r
575 @param Buffer Pointer to the data buffer to be written.\r
576 @param NumberOfBytes Number of bytes to written to the serial device.\r
577\r
578 @retval 0 NumberOfBytes is 0.\r
579 @retval >0 The number of bytes written to the serial device. \r
02018760 580 If this value is less than NumberOfBytes, then the write operation failed.\r
467d15ae 581\r
582**/\r
583UINTN\r
584EFIAPI\r
585SerialPortWrite (\r
586 IN UINT8 *Buffer,\r
587 IN UINTN NumberOfBytes\r
31122d8c 588 )\r
467d15ae 589{\r
31122d8c
LG
590 UINTN SerialRegisterBase;\r
591 UINTN Result;\r
592 UINTN Index;\r
593 UINTN FifoSize;\r
467d15ae 594\r
595 if (Buffer == NULL) {\r
596 return 0;\r
597 }\r
598\r
31122d8c
LG
599 SerialRegisterBase = GetSerialRegisterBase ();\r
600 if (SerialRegisterBase ==0) {\r
601 return 0;\r
602 }\r
603 \r
e5010d30
RN
604 if (NumberOfBytes == 0) {\r
605 //\r
606 // Flush the hardware\r
607 //\r
608\r
609 //\r
610 // Wait for both the transmit FIFO and shift register empty.\r
611 //\r
31122d8c 612 while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY));\r
e5010d30
RN
613\r
614 //\r
615 // Wait for the hardware flow control signal\r
616 //\r
31122d8c 617 while (!SerialPortWritable (SerialRegisterBase));\r
e5010d30
RN
618 return 0;\r
619 }\r
620\r
467d15ae 621 //\r
622 // Compute the maximum size of the Tx FIFO\r
623 //\r
624 FifoSize = 1;\r
625 if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFOE) != 0) {\r
626 if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFO64) == 0) {\r
627 FifoSize = 16;\r
628 } else {\r
31122d8c 629 FifoSize = PcdGet32 (PcdSerialExtendedTxFifoSize);\r
467d15ae 630 }\r
631 }\r
db662a64 632\r
467d15ae 633 Result = NumberOfBytes;\r
634 while (NumberOfBytes != 0) {\r
635 //\r
636 // Wait for the serial port to be ready, to make sure both the transmit FIFO\r
637 // and shift register empty.\r
638 //\r
31122d8c 639 while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & B_UART_LSR_TEMT) == 0);\r
467d15ae 640\r
641 //\r
642 // Fill then entire Tx FIFO\r
643 //\r
644 for (Index = 0; Index < FifoSize && NumberOfBytes != 0; Index++, NumberOfBytes--, Buffer++) {\r
e5010d30
RN
645 //\r
646 // Wait for the hardware flow control signal\r
647 //\r
31122d8c 648 while (!SerialPortWritable (SerialRegisterBase));\r
e5010d30 649\r
467d15ae 650 //\r
651 // Write byte to the transmit buffer.\r
652 //\r
31122d8c 653 SerialPortWriteRegister (SerialRegisterBase, R_UART_TXBUF, *Buffer);\r
467d15ae 654 }\r
655 }\r
656 return Result;\r
657}\r
658\r
659/**\r
660 Reads data from a serial device into a buffer.\r
661\r
662 @param Buffer Pointer to the data buffer to store the data read from the serial device.\r
663 @param NumberOfBytes Number of bytes to read from the serial device.\r
664\r
665 @retval 0 NumberOfBytes is 0.\r
666 @retval >0 The number of bytes read from the serial device. \r
667 If this value is less than NumberOfBytes, then the read operation failed.\r
668\r
669**/\r
670UINTN\r
671EFIAPI\r
672SerialPortRead (\r
673 OUT UINT8 *Buffer,\r
674 IN UINTN NumberOfBytes\r
31122d8c 675 )\r
467d15ae 676{\r
31122d8c 677 UINTN SerialRegisterBase;\r
467d15ae 678 UINTN Result;\r
679 UINT8 Mcr;\r
680\r
681 if (NULL == Buffer) {\r
682 return 0;\r
683 }\r
684\r
31122d8c
LG
685 SerialRegisterBase = GetSerialRegisterBase ();\r
686 if (SerialRegisterBase ==0) {\r
687 return 0;\r
688 }\r
689\r
690 Mcr = (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) & ~B_UART_MCR_RTS);\r
467d15ae 691 \r
692 for (Result = 0; NumberOfBytes-- != 0; Result++, Buffer++) {\r
693 //\r
694 // Wait for the serial port to have some data.\r
695 //\r
31122d8c 696 while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & B_UART_LSR_RXRDY) == 0) {\r
467d15ae 697 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {\r
698 //\r
699 // Set RTS to let the peer send some data\r
700 //\r
31122d8c 701 SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, (UINT8)(Mcr | B_UART_MCR_RTS));\r
467d15ae 702 }\r
703 }\r
704 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {\r
705 //\r
706 // Clear RTS to prevent peer from sending data\r
707 //\r
31122d8c 708 SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr);\r
467d15ae 709 }\r
710 \r
711 //\r
712 // Read byte from the receive buffer.\r
713 //\r
31122d8c 714 *Buffer = SerialPortReadRegister (SerialRegisterBase, R_UART_RXBUF);\r
467d15ae 715 }\r
716 \r
717 return Result;\r
718}\r
719\r
31122d8c 720\r
467d15ae 721/**\r
722 Polls a serial device to see if there is any data waiting to be read.\r
723\r
724 Polls aserial device to see if there is any data waiting to be read.\r
725 If there is data waiting to be read from the serial device, then TRUE is returned.\r
726 If there is no data waiting to be read from the serial device, then FALSE is returned.\r
727\r
728 @retval TRUE Data is waiting to be read from the serial device.\r
729 @retval FALSE There is no data waiting to be read from the serial device.\r
730\r
731**/\r
732BOOLEAN\r
733EFIAPI\r
734SerialPortPoll (\r
735 VOID\r
736 )\r
737{\r
31122d8c
LG
738 UINTN SerialRegisterBase;\r
739 \r
740 SerialRegisterBase = GetSerialRegisterBase ();\r
741 if (SerialRegisterBase ==0) {\r
742 return FALSE;\r
743 }\r
744\r
467d15ae 745 //\r
746 // Read the serial port status\r
747 //\r
31122d8c 748 if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & B_UART_LSR_RXRDY) != 0) {\r
467d15ae 749 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {\r
750 //\r
751 // Clear RTS to prevent peer from sending data\r
752 //\r
31122d8c 753 SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) & ~B_UART_MCR_RTS));\r
467d15ae 754 }\r
755 return TRUE;\r
756 } \r
757 \r
758 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {\r
759 //\r
760 // Set RTS to let the peer send some data\r
761 //\r
31122d8c 762 SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) | B_UART_MCR_RTS));\r
467d15ae 763 }\r
764 \r
765 return FALSE;\r
766}\r
c0e6c393
SZ
767\r
768/**\r
769 Sets the control bits on a serial device.\r
770\r
771 @param Control Sets the bits of Control that are settable.\r
772\r
773 @retval RETURN_SUCCESS The new control bits were set on the serial device.\r
774 @retval RETURN_UNSUPPORTED The serial device does not support this operation.\r
775 @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.\r
776\r
777**/\r
778RETURN_STATUS\r
779EFIAPI\r
780SerialPortSetControl (\r
781 IN UINT32 Control\r
782 )\r
783{\r
784 UINTN SerialRegisterBase;\r
785 UINT8 Mcr;\r
786\r
787 //\r
788 // First determine the parameter is invalid.\r
789 //\r
790 if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |\r
791 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0) {\r
792 return RETURN_UNSUPPORTED;\r
793 }\r
794\r
795 SerialRegisterBase = GetSerialRegisterBase ();\r
796 if (SerialRegisterBase ==0) {\r
797 return RETURN_UNSUPPORTED;\r
798 }\r
799\r
800 //\r
801 // Read the Modem Control Register.\r
802 //\r
803 Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR);\r
804 Mcr &= (~(B_UART_MCR_DTRC | B_UART_MCR_RTS));\r
805\r
806 if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {\r
807 Mcr |= B_UART_MCR_DTRC;\r
808 }\r
809\r
810 if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {\r
811 Mcr |= B_UART_MCR_RTS;\r
812 }\r
813\r
814 //\r
815 // Write the Modem Control Register.\r
816 //\r
817 SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr);\r
818\r
819 return RETURN_SUCCESS;\r
820}\r
821\r
822/**\r
823 Retrieve the status of the control bits on a serial device.\r
824\r
825 @param Control A pointer to return the current control signals from the serial device.\r
826\r
827 @retval RETURN_SUCCESS The control bits were read from the serial device.\r
828 @retval RETURN_UNSUPPORTED The serial device does not support this operation.\r
829 @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.\r
830\r
831**/\r
832RETURN_STATUS\r
833EFIAPI\r
834SerialPortGetControl (\r
835 OUT UINT32 *Control\r
836 )\r
837{\r
838 UINTN SerialRegisterBase;\r
839 UINT8 Msr;\r
840 UINT8 Mcr;\r
841 UINT8 Lsr;\r
842\r
843 SerialRegisterBase = GetSerialRegisterBase ();\r
844 if (SerialRegisterBase ==0) {\r
845 return RETURN_UNSUPPORTED;\r
846 }\r
847\r
848 *Control = 0;\r
849\r
850 //\r
851 // Read the Modem Status Register.\r
852 //\r
853 Msr = SerialPortReadRegister (SerialRegisterBase, R_UART_MSR);\r
854\r
855 if ((Msr & B_UART_MSR_CTS) == B_UART_MSR_CTS) {\r
856 *Control |= EFI_SERIAL_CLEAR_TO_SEND;\r
857 }\r
858\r
859 if ((Msr & B_UART_MSR_DSR) == B_UART_MSR_DSR) {\r
860 *Control |= EFI_SERIAL_DATA_SET_READY;\r
861 }\r
862\r
863 if ((Msr & B_UART_MSR_RI) == B_UART_MSR_RI) {\r
864 *Control |= EFI_SERIAL_RING_INDICATE;\r
865 }\r
866\r
867 if ((Msr & B_UART_MSR_DCD) == B_UART_MSR_DCD) {\r
868 *Control |= EFI_SERIAL_CARRIER_DETECT;\r
869 }\r
870\r
871 //\r
872 // Read the Modem Control Register.\r
873 //\r
874 Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR);\r
875\r
876 if ((Mcr & B_UART_MCR_DTRC) == B_UART_MCR_DTRC) {\r
877 *Control |= EFI_SERIAL_DATA_TERMINAL_READY;\r
878 }\r
879\r
880 if ((Mcr & B_UART_MCR_RTS) == B_UART_MCR_RTS) {\r
881 *Control |= EFI_SERIAL_REQUEST_TO_SEND;\r
882 }\r
883\r
884 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {\r
885 *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
886 }\r
887\r
888 //\r
889 // Read the Line Status Register.\r
890 //\r
891 Lsr = SerialPortReadRegister (SerialRegisterBase, R_UART_LSR);\r
892\r
893 if ((Lsr & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) == (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) {\r
894 *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;\r
895 }\r
896\r
897 if ((Lsr & B_UART_LSR_RXRDY) == 0) {\r
898 *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;\r
899 }\r
900\r
901 return RETURN_SUCCESS;\r
902}\r
903\r
904/**\r
905 Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,\r
906 data bits, and stop bits on a serial device.\r
907\r
908 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the\r
909 device's default interface speed.\r
910 On output, the value actually set.\r
911 @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the\r
912 serial interface. A ReceiveFifoDepth value of 0 will use\r
913 the device's default FIFO depth.\r
914 On output, the value actually set.\r
915 @param Timeout The requested time out for a single character in microseconds.\r
916 This timeout applies to both the transmit and receive side of the\r
917 interface. A Timeout value of 0 will use the device's default time\r
918 out value.\r
919 On output, the value actually set.\r
920 @param Parity The type of parity to use on this serial device. A Parity value of\r
921 DefaultParity will use the device's default parity value.\r
922 On output, the value actually set.\r
923 @param DataBits The number of data bits to use on the serial device. A DataBits\r
924 vaule of 0 will use the device's default data bit setting.\r
925 On output, the value actually set.\r
926 @param StopBits The number of stop bits to use on this serial device. A StopBits\r
927 value of DefaultStopBits will use the device's default number of\r
928 stop bits.\r
929 On output, the value actually set.\r
930\r
931 @retval RETURN_SUCCESS The new attributes were set on the serial device.\r
932 @retval RETURN_UNSUPPORTED The serial device does not support this operation.\r
933 @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value.\r
934 @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.\r
935\r
936**/\r
937RETURN_STATUS\r
938EFIAPI\r
939SerialPortSetAttributes (\r
940 IN OUT UINT64 *BaudRate,\r
941 IN OUT UINT32 *ReceiveFifoDepth,\r
942 IN OUT UINT32 *Timeout,\r
943 IN OUT EFI_PARITY_TYPE *Parity,\r
944 IN OUT UINT8 *DataBits,\r
945 IN OUT EFI_STOP_BITS_TYPE *StopBits\r
946 )\r
947{\r
948 UINTN SerialRegisterBase;\r
949 UINT32 SerialBaudRate;\r
950 UINTN Divisor;\r
951 UINT8 Lcr;\r
952 UINT8 LcrData;\r
953 UINT8 LcrParity;\r
954 UINT8 LcrStop;\r
955\r
956 SerialRegisterBase = GetSerialRegisterBase ();\r
957 if (SerialRegisterBase ==0) {\r
958 return RETURN_UNSUPPORTED;\r
959 }\r
960\r
961 //\r
962 // Check for default settings and fill in actual values.\r
963 //\r
964 if (*BaudRate == 0) {\r
965 *BaudRate = PcdGet32 (PcdSerialBaudRate);\r
966 }\r
967 SerialBaudRate = (UINT32) *BaudRate;\r
968\r
969 if (*DataBits == 0) {\r
970 LcrData = (UINT8) (PcdGet8 (PcdSerialLineControl) & 0x3);\r
971 *DataBits = LcrData + 5;\r
972 } else {\r
973 if ((*DataBits < 5) || (*DataBits > 8)) {\r
974 return RETURN_INVALID_PARAMETER;\r
975 }\r
976 //\r
977 // Map 5..8 to 0..3\r
978 //\r
979 LcrData = (UINT8) (*DataBits - (UINT8) 5);\r
980 }\r
981\r
982 if (*Parity == DefaultParity) {\r
983 LcrParity = (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 3) & 0x7);\r
984 switch (LcrParity) {\r
985 case 0:\r
986 *Parity = NoParity;\r
987 break;\r
988\r
989 case 3:\r
990 *Parity = EvenParity;\r
991 break;\r
992\r
993 case 1:\r
994 *Parity = OddParity;\r
995 break;\r
996\r
997 case 7:\r
998 *Parity = SpaceParity;\r
999 break;\r
1000\r
1001 case 5:\r
1002 *Parity = MarkParity;\r
1003 break;\r
1004\r
1005 default:\r
1006 break;\r
1007 }\r
1008 } else {\r
1009 if ((*Parity < NoParity) || (*Parity > SpaceParity)) {\r
1010 return RETURN_INVALID_PARAMETER;\r
1011 }\r
1012 switch (*Parity) {\r
1013 case NoParity:\r
1014 LcrParity = 0;\r
1015 break;\r
1016\r
1017 case EvenParity:\r
1018 LcrParity = 3;\r
1019 break;\r
1020\r
1021 case OddParity:\r
1022 LcrParity = 1;\r
1023 break;\r
1024\r
1025 case SpaceParity:\r
1026 LcrParity = 7;\r
1027 break;\r
1028\r
1029 case MarkParity:\r
1030 LcrParity = 5;\r
1031 break;\r
1032\r
1033 default:\r
1034 break;\r
1035 }\r
1036 }\r
1037\r
1038 if (*StopBits == DefaultStopBits) {\r
1039 LcrStop = (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 2) & 0x1);\r
1040 switch (LcrStop) {\r
1041 case 0:\r
1042 *StopBits = OneStopBit;\r
1043 break;\r
1044\r
1045 case 1:\r
1046 if (*DataBits == 5) {\r
1047 *StopBits = OneFiveStopBits;\r
1048 } else {\r
1049 *StopBits = TwoStopBits;\r
1050 }\r
1051 break;\r
1052\r
1053 default:\r
1054 break;\r
1055 }\r
1056 } else {\r
1057 if ((*StopBits < OneStopBit) || (*StopBits > TwoStopBits)) {\r
1058 return RETURN_INVALID_PARAMETER;\r
1059 }\r
1060 switch (*StopBits) {\r
1061 case OneStopBit:\r
1062 LcrStop = 0;\r
1063 break;\r
1064\r
1065 case OneFiveStopBits:\r
1066 case TwoStopBits:\r
1067 LcrStop = 1;\r
1068 break;\r
1069\r
1070 default:\r
1071 break;\r
1072 }\r
1073 }\r
1074\r
1075 //\r
1076 // Calculate divisor for baud generator\r
1077 // Ref_Clk_Rate / Baud_Rate / 16\r
1078 //\r
1079 Divisor = PcdGet32 (PcdSerialClockRate) / (SerialBaudRate * 16);\r
1080 if ((PcdGet32 (PcdSerialClockRate) % (SerialBaudRate * 16)) >= SerialBaudRate * 8) {\r
1081 Divisor++;\r
1082 }\r
1083\r
1084 //\r
1085 // Configure baud rate\r
1086 //\r
1087 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB);\r
1088 SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8) (Divisor >> 8));\r
1089 SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8) (Divisor & 0xff));\r
1090\r
1091 //\r
1092 // Clear DLAB and configure Data Bits, Parity, and Stop Bits.\r
1093 // Strip reserved bits from line control value\r
1094 //\r
1095 Lcr = (UINT8) ((LcrParity << 3) | (LcrStop << 2) | LcrData);\r
1096 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8) (Lcr & 0x3F));\r
1097\r
1098 return RETURN_SUCCESS;\r
1099}\r
1100\r