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