2 UART Serial Port library functions
4 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/IoLib.h>
17 #include <Library/SerialPortLib.h>
19 //---------------------------------------------
20 // UART Register Offsets
21 //---------------------------------------------
22 #define BAUD_LOW_OFFSET 0x00
23 #define BAUD_HIGH_OFFSET 0x01
24 #define IER_OFFSET 0x01
25 #define LCR_SHADOW_OFFSET 0x01
26 #define FCR_SHADOW_OFFSET 0x02
27 #define IR_CONTROL_OFFSET 0x02
28 #define FCR_OFFSET 0x02
29 #define EIR_OFFSET 0x02
30 #define BSR_OFFSET 0x03
31 #define LCR_OFFSET 0x03
32 #define MCR_OFFSET 0x04
33 #define LSR_OFFSET 0x05
34 #define MSR_OFFSET 0x06
36 //---------------------------------------------
37 // UART Register Bit Defines
38 //---------------------------------------------
39 #define LSR_TXRDY 0x20
49 //---------------------------------------------
51 //---------------------------------------------
52 UINT16 gUartBase
= 0x3F8;
60 Initialize the serial device hardware.
62 If no initialization is required, then return RETURN_SUCCESS.
63 If the serial device was successfuly initialized, then return RETURN_SUCCESS.
64 If the serial device could not be initialized, then return RETURN_DEVICE_ERROR.
66 @retval RETURN_SUCCESS The serial device was initialized.
67 @retval RETURN_DEVICE_ERROR The serail device could not be initialized.
72 SerialPortInitialize (
83 Data
= (UINT8
) (gData
- (UINT8
) 5);
86 // Calculate divisor for baud generator
88 Divisor
= 115200 / gBps
;
91 // Set communications format
93 OutputData
= (UINT8
) ((DLAB
<< 7) | (gBreakSet
<< 6) | (gParity
<< 3) | (gStop
<< 2) | Data
);
94 IoWrite8 ((UINTN
) (gUartBase
+ LCR_OFFSET
), OutputData
);
97 // Configure baud rate
99 IoWrite8 ((UINTN
) (gUartBase
+ BAUD_HIGH_OFFSET
), (UINT8
) (Divisor
>> 8));
100 IoWrite8 ((UINTN
) (gUartBase
+ BAUD_LOW_OFFSET
), (UINT8
) (Divisor
& 0xff));
103 // Switch back to bank 0
105 OutputData
= (UINT8
) ((~DLAB
<< 7) | (gBreakSet
<< 6) | (gParity
<< 3) | (gStop
<< 2) | Data
);
106 IoWrite8 ((UINTN
) (gUartBase
+ LCR_OFFSET
), OutputData
);
108 return RETURN_SUCCESS
;
112 Write data from buffer to serial device.
114 Writes NumberOfBytes data bytes from Buffer to the serial device.
115 The number of bytes actually written to the serial device is returned.
116 If the return value is less than NumberOfBytes, then the write operation failed.
118 If Buffer is NULL, then ASSERT().
120 If NumberOfBytes is zero, then return 0.
122 @param Buffer Pointer to the data buffer to be written.
123 @param NumberOfBytes Number of bytes to written to the serial device.
125 @retval 0 NumberOfBytes is 0.
126 @retval >0 The number of bytes written to the serial device.
127 If this value is less than NumberOfBytes, then the write operation failed.
134 IN UINTN NumberOfBytes
140 if (Buffer
== NULL
) {
144 Result
= NumberOfBytes
;
146 while ((NumberOfBytes
--) != 0) {
148 // Wait for the serail port to be ready.
151 Data
= IoRead8 ((UINT16
) gUartBase
+ LSR_OFFSET
);
152 } while ((Data
& LSR_TXRDY
) == 0);
153 IoWrite8 ((UINT16
) gUartBase
, *Buffer
++);
161 Reads data from a serial device into a buffer.
163 @param Buffer Pointer to the data buffer to store the data read from the serial device.
164 @param NumberOfBytes Number of bytes to read from the serial device.
166 @retval 0 NumberOfBytes is 0.
167 @retval >0 The number of bytes read from the serial device.
168 If this value is less than NumberOfBytes, then the read operation failed.
175 IN UINTN NumberOfBytes
181 if (NULL
== Buffer
) {
185 Result
= NumberOfBytes
;
187 while ((NumberOfBytes
--) != 0) {
189 // Wait for the serail port to be ready.
192 Data
= IoRead8 ((UINT16
) gUartBase
+ LSR_OFFSET
);
193 } while ((Data
& LSR_RXDA
) == 0);
195 *Buffer
++ = IoRead8 ((UINT16
) gUartBase
);
202 Polls a serial device to see if there is any data waiting to be read.
204 Polls aserial device to see if there is any data waiting to be read.
205 If there is data waiting to be read from the serial device, then TRUE is returned.
206 If there is no data waiting to be read from the serial device, then FALSE is returned.
208 @retval TRUE Data is waiting to be read from the serial device.
209 @retval FALSE There is no data waiting to be read from the serial device.
221 // Read the serial port status.
223 Data
= IoRead8 ((UINT16
) gUartBase
+ LSR_OFFSET
);
225 return (BOOLEAN
) ((Data
& LSR_RXDA
) != 0);
229 Sets the control bits on a serial device.
231 @param Control Sets the bits of Control that are settable.
233 @retval RETURN_SUCCESS The new control bits were set on the serial device.
234 @retval RETURN_UNSUPPORTED The serial device does not support this operation.
235 @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.
240 SerialPortSetControl (
247 // First determine the parameter is invalid.
249 if ((Control
& (~(EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
))) != 0) {
250 return RETURN_UNSUPPORTED
;
254 // Read the Modem Control Register.
256 Mcr
= IoRead8 ((UINT16
) gUartBase
+ MCR_OFFSET
);
257 Mcr
&= (~(MCR_DTRC
| MCR_RTS
));
259 if ((Control
& EFI_SERIAL_DATA_TERMINAL_READY
) == EFI_SERIAL_DATA_TERMINAL_READY
) {
263 if ((Control
& EFI_SERIAL_REQUEST_TO_SEND
) == EFI_SERIAL_REQUEST_TO_SEND
) {
268 // Write the Modem Control Register.
270 IoWrite8 ((UINT16
) gUartBase
+ MCR_OFFSET
, Mcr
);
272 return RETURN_SUCCESS
;
276 Retrieve the status of the control bits on a serial device.
278 @param Control A pointer to return the current control signals from the serial device.
280 @retval RETURN_SUCCESS The control bits were read from the serial device.
281 @retval RETURN_UNSUPPORTED The serial device does not support this operation.
282 @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.
287 SerialPortGetControl (
298 // Read the Modem Status Register.
300 Msr
= IoRead8 ((UINT16
) gUartBase
+ MSR_OFFSET
);
302 if ((Msr
& MSR_CTS
) == MSR_CTS
) {
303 *Control
|= EFI_SERIAL_CLEAR_TO_SEND
;
306 if ((Msr
& MSR_DSR
) == MSR_DSR
) {
307 *Control
|= EFI_SERIAL_DATA_SET_READY
;
310 if ((Msr
& MSR_RI
) == MSR_RI
) {
311 *Control
|= EFI_SERIAL_RING_INDICATE
;
314 if ((Msr
& MSR_DCD
) == MSR_DCD
) {
315 *Control
|= EFI_SERIAL_CARRIER_DETECT
;
319 // Read the Modem Control Register.
321 Mcr
= IoRead8 ((UINT16
) gUartBase
+ MCR_OFFSET
);
323 if ((Mcr
& MCR_DTRC
) == MCR_DTRC
) {
324 *Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
327 if ((Mcr
& MCR_RTS
) == MCR_RTS
) {
328 *Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
332 // Read the Line Status Register.
334 Lsr
= IoRead8 ((UINT16
) gUartBase
+ LSR_OFFSET
);
336 if ((Lsr
& LSR_TXRDY
) == LSR_TXRDY
) {
337 *Control
|= EFI_SERIAL_OUTPUT_BUFFER_EMPTY
;
340 if ((Lsr
& LSR_RXDA
) == 0) {
341 *Control
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
344 return RETURN_SUCCESS
;
348 Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
349 data bits, and stop bits on a serial device.
351 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the
352 device's default interface speed.
353 On output, the value actually set.
354 @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the
355 serial interface. A ReceiveFifoDepth value of 0 will use
356 the device's default FIFO depth.
357 On output, the value actually set.
358 @param Timeout The requested time out for a single character in microseconds.
359 This timeout applies to both the transmit and receive side of the
360 interface. A Timeout value of 0 will use the device's default time
362 On output, the value actually set.
363 @param Parity The type of parity to use on this serial device. A Parity value of
364 DefaultParity will use the device's default parity value.
365 On output, the value actually set.
366 @param DataBits The number of data bits to use on the serial device. A DataBits
367 vaule of 0 will use the device's default data bit setting.
368 On output, the value actually set.
369 @param StopBits The number of stop bits to use on this serial device. A StopBits
370 value of DefaultStopBits will use the device's default number of
372 On output, the value actually set.
374 @retval RETURN_SUCCESS The new attributes were set on the serial device.
375 @retval RETURN_UNSUPPORTED The serial device does not support this operation.
376 @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value.
377 @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.
382 SerialPortSetAttributes (
383 IN OUT UINT64
*BaudRate
,
384 IN OUT UINT32
*ReceiveFifoDepth
,
385 IN OUT UINT32
*Timeout
,
386 IN OUT EFI_PARITY_TYPE
*Parity
,
387 IN OUT UINT8
*DataBits
,
388 IN OUT EFI_STOP_BITS_TYPE
*StopBits
398 // Check for default settings and fill in actual values.
400 if (*BaudRate
== 0) {
404 if (*DataBits
== 0) {
408 if (*Parity
== DefaultParity
) {
412 if (*StopBits
== DefaultStopBits
) {
413 *StopBits
= OneStopBit
;
416 if ((*DataBits
< 5) || (*DataBits
> 8)) {
417 return RETURN_INVALID_PARAMETER
;
420 if ((*Parity
< NoParity
) || (*Parity
> SpaceParity
)) {
421 return RETURN_INVALID_PARAMETER
;
424 if ((*StopBits
< OneStopBit
) || (*StopBits
> TwoStopBits
)) {
425 return RETURN_INVALID_PARAMETER
;
431 LcrData
= (UINT8
) (*DataBits
- (UINT8
) 5);
463 case OneFiveStopBits
:
473 // Calculate divisor for baud generator
475 Divisor
= 115200 / (UINTN
) *BaudRate
;
478 // Set communications format
480 OutputData
= (UINT8
) ((DLAB
<< 7) | (gBreakSet
<< 6) | (LcrParity
<< 3) | (LcrStop
<< 2) | LcrData
);
481 IoWrite8 ((UINTN
) (gUartBase
+ LCR_OFFSET
), OutputData
);
484 // Configure baud rate
486 IoWrite8 ((UINTN
) (gUartBase
+ BAUD_HIGH_OFFSET
), (UINT8
) (Divisor
>> 8));
487 IoWrite8 ((UINTN
) (gUartBase
+ BAUD_LOW_OFFSET
), (UINT8
) (Divisor
& 0xff));
490 // Switch back to bank 0
492 OutputData
= (UINT8
) ((~DLAB
<< 7) | (gBreakSet
<< 6) | (LcrParity
<< 3) | (LcrStop
<< 2) | LcrData
);
493 IoWrite8 ((UINTN
) (gUartBase
+ LCR_OFFSET
), OutputData
);
495 return RETURN_SUCCESS
;