summaryrefslogtreecommitdiffstats
path: root/src/include/ipxe/uart.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/ipxe/uart.h')
-rw-r--r--src/include/ipxe/uart.h217
1 files changed, 131 insertions, 86 deletions
diff --git a/src/include/ipxe/uart.h b/src/include/ipxe/uart.h
index c63eae615..f2ecf3ce9 100644
--- a/src/include/ipxe/uart.h
+++ b/src/include/ipxe/uart.h
@@ -3,130 +3,175 @@
/** @file
*
- * 16550-compatible UART
+ * Generic UART
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/list.h>
-/** Transmitter holding register */
-#define UART_THR 0x00
-
-/** Receiver buffer register */
-#define UART_RBR 0x00
-
-/** Interrupt enable register */
-#define UART_IER 0x01
+/** A generic UART */
+struct uart {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Name */
+ const char *name;
+ /** List of registered UARTs */
+ struct list_head list;
+
+ /** Baud rate (if specified) */
+ unsigned int baud;
+
+ /** UART operations */
+ struct uart_operations *op;
+ /** Driver-private data */
+ void *priv;
+};
-/** FIFO control register */
-#define UART_FCR 0x02
-#define UART_FCR_FE 0x01 /**< FIFO enable */
+/** UART operations */
+struct uart_operations {
+ /**
+ * Transmit byte
+ *
+ * @v uart UART
+ * @v byte Byte to transmit
+ * @ret rc Return status code
+ */
+ void ( * transmit ) ( struct uart *uart, uint8_t byte );
+ /**
+ * Check if data is ready
+ *
+ * @v uart UART
+ * @ret ready Data is ready
+ */
+ int ( * data_ready ) ( struct uart *uart );
+ /**
+ * Receive byte
+ *
+ * @v uart UART
+ * @ret byte Received byte
+ */
+ uint8_t ( * receive ) ( struct uart *uart );
+ /**
+ * Initialise UART
+ *
+ * @v uart UART
+ * @ret rc Return status code
+ */
+ int ( * init ) ( struct uart *uart );
+ /**
+ * Flush transmitted data
+ *
+ * @v uart UART
+ */
+ void ( * flush ) ( struct uart *uart );
+};
-/** Line control register */
-#define UART_LCR 0x03
-#define UART_LCR_WLS0 0x01 /**< Word length select bit 0 */
-#define UART_LCR_WLS1 0x02 /**< Word length select bit 1 */
-#define UART_LCR_STB 0x04 /**< Number of stop bits */
-#define UART_LCR_PEN 0x08 /**< Parity enable */
-#define UART_LCR_EPS 0x10 /**< Even parity select */
-#define UART_LCR_DLAB 0x80 /**< Divisor latch access bit */
+/**
+ * Transmit byte
+ *
+ * @v uart UART
+ * @v byte Byte to transmit
+ * @ret rc Return status code
+ */
+static inline __attribute__ (( always_inline )) void
+uart_transmit ( struct uart *uart, uint8_t byte ) {
-#define UART_LCR_WORD_LEN(x) ( ( (x) - 5 ) << 0 ) /**< Word length */
-#define UART_LCR_STOP_BITS(x) ( ( (x) - 1 ) << 2 ) /**< Stop bits */
-#define UART_LCR_PARITY(x) ( ( (x) - 0 ) << 3 ) /**< Parity */
+ uart->op->transmit ( uart, byte );
+}
/**
- * Calculate line control register value
+ * Check if data is ready
*
- * @v word_len Word length (5-8)
- * @v parity Parity (0=none, 1=odd, 3=even)
- * @v stop_bits Stop bits (1-2)
- * @ret lcr Line control register value
+ * @v uart UART
+ * @ret ready Data is ready
*/
-#define UART_LCR_WPS( word_len, parity, stop_bits ) \
- ( UART_LCR_WORD_LEN ( (word_len) ) | \
- UART_LCR_PARITY ( (parity) ) | \
- UART_LCR_STOP_BITS ( (stop_bits) ) )
-
-/** Default LCR value: 8 data bits, no parity, one stop bit */
-#define UART_LCR_8N1 UART_LCR_WPS ( 8, 0, 1 )
+static inline __attribute__ (( always_inline )) int
+uart_data_ready ( struct uart *uart ) {
-/** Modem control register */
-#define UART_MCR 0x04
-#define UART_MCR_DTR 0x01 /**< Data terminal ready */
-#define UART_MCR_RTS 0x02 /**< Request to send */
+ return uart->op->data_ready ( uart );
+}
-/** Line status register */
-#define UART_LSR 0x05
-#define UART_LSR_DR 0x01 /**< Data ready */
-#define UART_LSR_THRE 0x20 /**< Transmitter holding register empty */
-#define UART_LSR_TEMT 0x40 /**< Transmitter empty */
+/**
+ * Receive byte
+ *
+ * @v uart UART
+ * @ret byte Received byte
+ */
+static inline __attribute__ (( always_inline )) uint8_t
+uart_receive ( struct uart *uart ) {
-/** Scratch register */
-#define UART_SCR 0x07
+ return uart->op->receive ( uart );
+}
-/** Divisor latch (least significant byte) */
-#define UART_DLL 0x00
+/**
+ * Initialise UART
+ *
+ * @v uart UART
+ * @ret rc Return status code
+ */
+static inline __attribute__ (( always_inline )) int
+uart_init ( struct uart *uart ) {
-/** Divisor latch (most significant byte) */
-#define UART_DLM 0x01
+ return uart->op->init ( uart );
+}
-/** Maximum baud rate */
-#define UART_MAX_BAUD 115200
+/**
+ * Flush transmitted data
+ *
+ * @v uart UART
+ */
+static inline __attribute__ (( always_inline )) void
+uart_flush ( struct uart *uart ) {
-/** A 16550-compatible UART */
-struct uart {
- /** I/O port base address */
- void *base;
- /** Baud rate divisor */
- uint16_t divisor;
- /** Line control register */
- uint8_t lcr;
-};
+ uart->op->flush ( uart );
+}
-/** Symbolic names for port indexes */
-enum uart_port {
- COM1 = 1,
- COM2 = 2,
- COM3 = 3,
- COM4 = 4,
-};
+extern struct list_head uarts;
+extern struct uart_operations null_uart_operations;
-#include <bits/uart.h>
+/**
+ * Get reference to UART
+ *
+ * @v uart UART
+ * @ret uart UART
+ */
+static inline __attribute__ (( always_inline )) struct uart *
+uart_get ( struct uart *uart ) {
-void uart_write ( struct uart *uart, unsigned int addr, uint8_t data );
-uint8_t uart_read ( struct uart *uart, unsigned int addr );
-int uart_select ( struct uart *uart, unsigned int port );
+ ref_get ( &uart->refcnt );
+ return uart;
+}
/**
- * Check if received data is ready
+ * Drop reference to UART
*
* @v uart UART
- * @ret ready Data is ready
*/
-static inline int uart_data_ready ( struct uart *uart ) {
- uint8_t lsr;
+static inline __attribute__ (( always_inline )) void
+uart_put ( struct uart *uart ) {
- lsr = uart_read ( uart, UART_LSR );
- return ( lsr & UART_LSR_DR );
+ ref_put ( &uart->refcnt );
}
/**
- * Receive data
+ * Nullify UART
*
* @v uart UART
- * @ret data Data
*/
-static inline uint8_t uart_receive ( struct uart *uart ) {
+static inline __attribute__ (( always_inline )) void
+uart_nullify ( struct uart *uart ) {
- return uart_read ( uart, UART_RBR );
+ uart->op = &null_uart_operations;
}
-extern void uart_transmit ( struct uart *uart, uint8_t data );
-extern void uart_flush ( struct uart *uart );
-extern int uart_exists ( struct uart *uart );
-extern int uart_init ( struct uart *uart, unsigned int baud, uint8_t lcr );
+extern struct uart * alloc_uart ( size_t priv_len );
+extern int uart_register ( struct uart *uart );
+extern int uart_register_fixed ( void );
+extern void uart_unregister ( struct uart *uart );
+extern struct uart * uart_find ( const char *name );
#endif /* _IPXE_UART_H */