1 /** @file
2   Serial I/O Port library functions with no library constructor/destructor
3 
4   Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
5 
6 
7   This program and the accompanying materials are licensed and made available under
8 
9   the terms and conditions of the BSD License that accompanies this distribution.
10 
11   The full text of the license may be found at
12 
13   http://opensource.org/licenses/bsd-license.php.
14 
15 
16 
17   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
18 
19   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 
21 
22 
23   This software and associated documentation
24   (if any) is furnished under a license and may only be used or
25   copied in accordance with the terms of the license.  Except as
26   permitted by such license, no part of this software or
27   documentation may be reproduced, stored in a retrieval system, or
28   transmitted in any form or by any means without the express written
29   consent of Intel Corporation.
30 
31   Module Name:  SerialPortLib.c
32 
33 **/
34 
35 #include "PlatformSerialPortLib.h"
36 
37 UINT16 gComBase  = 0x3f8;
38 UINTN  gBps      = 115200;
39 UINT8  gData     = 8;
40 UINT8  gStop     = 1;
41 UINT8  gParity   = 0;
42 UINT8  gBreakSet = 0;
43 
44 /**
45   Initialize Serial Port
46 
47   The Baud Rate Divisor registers are programmed and the LCR
48   is used to configure the communications format. Hard coded
UARTInitialize(VOID)49   UART config comes from globals in DebugSerialPlatform lib.
50 
51   @param None
52 
53   @retval None
54 
55 **/
56 RETURN_STATUS
57 EFIAPI
58 UARTInitialize (
59   VOID
60   )
61 {
62   UINTN Divisor;
63   UINT8 OutputData;
64   UINT8 Data;
65 
66   //
67   // Map 5..8 to 0..3
68   //
69   Data = (UINT8) (gData - (UINT8) 5);
70 
71   //
72   // Calculate divisor for baud generator
73   //
74   Divisor = 115200 / gBps;
75 
76   //
77   // Set communications format
78   //
79   OutputData = (UINT8) ((DLAB << 7) | ((gBreakSet << 6) | ((gParity << 3) | ((gStop << 2) | Data))));
80   IoWrite8 (gComBase + LCR_OFFSET, OutputData);
81 
82   //
83   // Configure baud rate
84   //
85   IoWrite8 (gComBase + BAUD_HIGH_OFFSET, (UINT8) (Divisor >> 8));
86   IoWrite8 (gComBase + BAUD_LOW_OFFSET, (UINT8) (Divisor & 0xff));
87 
88   //
89   // Switch back to bank 0
90   //
91   OutputData = (UINT8) ((~DLAB << 7) | ((gBreakSet << 6) | ((gParity << 3) | ((gStop << 2) | Data))));
92   IoWrite8 (gComBase + LCR_OFFSET, OutputData);
93 
94   return RETURN_SUCCESS;
95 }
96 
97 /**
SerialPortInitialize(VOID)98   Common function to initialize UART Serial device and USB Serial device.
99 
100   @param None
101 
102   @retval None
103 
104 **/
105 RETURN_STATUS
106 EFIAPI
107 SerialPortInitialize (
108   VOID
109   )
110 {
111 
112   UARTInitialize ();
113 
114 
115   return RETURN_SUCCESS;
116 }
117 
118 /**
119   Write data to serial device.
120 
121   If the buffer is NULL, then return 0;
122   if NumberOfBytes is zero, then return 0.
123 
UARTDbgOut(IN UINT8 * Buffer,IN UINTN NumberOfBytes)124   @param  Buffer           Point of data buffer which need to be writed.
125   @param  NumberOfBytes    Number of output bytes which are cached in Buffer.
126 
127   @retval 0                Write data failed.
128   @retval !0               Actual number of bytes writed to serial device.
129 
130 **/
131 UINTN
132 EFIAPI
133 UARTDbgOut (
134   IN UINT8     *Buffer,
135   IN UINTN     NumberOfBytes
136 )
137 {
138   UINTN Result;
139   UINT8 Data;
140 
141   if (NULL == Buffer) {
142     return 0;
143   }
144 
145   Result = NumberOfBytes;
146 
147   while (NumberOfBytes--) {
148     //
149     // Wait for the serial port to be ready.
150     //
151     do {
152       Data = IoRead8 ((UINT16) PcdGet64 (PcdSerialRegisterBase) + LSR_OFFSET);
153     } while ((Data & LSR_TXRDY) == 0);
154     IoWrite8 ((UINT16) PcdGet64 (PcdSerialRegisterBase), *Buffer++);
155   }
156 
157   return Result;
158 }
159 
SerialPortWrite(IN UINT8 * Buffer,IN UINTN NumberOfBytes)160 /**
161   Common function to write data to UART Serial device and USB Serial device.
162 
163   @param  Buffer           Point of data buffer which need to be writed.
164   @param  NumberOfBytes    Number of output bytes which are cached in Buffer.
165 
166 **/
167 UINTN
168 EFIAPI
169 SerialPortWrite (
170   IN UINT8     *Buffer,
171   IN UINTN     NumberOfBytes
172 )
173 {
174   if (FeaturePcdGet (PcdStatusCodeUseIsaSerial)) {
175     UARTDbgOut (Buffer, NumberOfBytes);
176   }
177 
178   return RETURN_SUCCESS;
179 }
180 
181 /**
182   Read data from serial device and save the datas in buffer.
183 
184   If the buffer is NULL, then return 0;
185   if NumberOfBytes is zero, then return 0.
186 
UARTDbgIn(OUT UINT8 * Buffer,IN UINTN NumberOfBytes)187   @param  Buffer           Point of data buffer which need to be writed.
188   @param  NumberOfBytes    Number of output bytes which are cached in Buffer.
189 
190   @retval 0                Read data failed.
191   @retval !0               Actual number of bytes raed to serial device.
192 
193 **/
194 UINTN
195 EFIAPI
196 UARTDbgIn (
197   OUT UINT8     *Buffer,
198   IN  UINTN     NumberOfBytes
199 )
200 {
201   UINTN Result;
202   UINT8 Data;
203 
204   if (NULL == Buffer) {
205     return 0;
206   }
207 
208   Result = NumberOfBytes;
209 
210   while (NumberOfBytes--) {
211     //
212     // Wait for the serial port to be ready.
213     //
214     do {
215       Data = IoRead8 ((UINT16) PcdGet64 (PcdSerialRegisterBase) + LSR_OFFSET);
216     } while ((Data & LSR_RXDA) == 0);
217 
218     *Buffer++ = IoRead8 ((UINT16) PcdGet64 (PcdSerialRegisterBase));
219   }
220 
221   return Result;
222 }
223 
SerialPortRead(OUT UINT8 * Buffer,IN UINTN NumberOfBytes)224 /**
225   Common function to Read data from UART serial device, USB serial device and save the datas in buffer.
226 
227   @param  Buffer           Point of data buffer which need to be writed.
228   @param  NumberOfBytes    Number of output bytes which are cached in Buffer.
229 
230 **/
231 UINTN
232 EFIAPI
233 SerialPortRead (
234   OUT UINT8     *Buffer,
235   IN  UINTN     NumberOfBytes
236 )
237 {
238   if (FeaturePcdGet (PcdStatusCodeUseIsaSerial)) {
239     UARTDbgIn (Buffer, NumberOfBytes);
240   }
241 
242   return RETURN_SUCCESS;
243 }
244 
245 
246 /**
247   Polls a serial device to see if there is any data waiting to be read.
248 
249   Polls aserial device to see if there is any data waiting to be read.
SerialPortPoll(VOID)250   If there is data waiting to be read from the serial device, then TRUE is returned.
251   If there is no data waiting to be read from the serial device, then FALSE is returned.
252 
253   @retval TRUE             Data is waiting to be read from the serial device.
254   @retval FALSE            There is no data waiting to be read from the serial device.
255 
256 **/
257 BOOLEAN
258 EFIAPI
259 SerialPortPoll (
260   VOID
261   )
262 {
263   UINT8  Data;
264 
265   //
266   // Read the serial port status.
267   //
268   Data = IoRead8 ((UINT16) PcdGet64 (PcdSerialRegisterBase) + LSR_OFFSET);
269 
270   return (BOOLEAN) ((Data & LSR_RXDA) != 0);
271 }
272