| /* |
| * Copyright (C) 2025 Michael Brown <mbrown@fensystems.co.uk>. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation; either version 2 of the |
| * License, or any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| * 02110-1301, USA. |
| * |
| * You can also choose to distribute this program under the terms of |
| * the Unmodified Binary Distribution Licence (as given in the file |
| * COPYING.UBDL), provided that you have satisfied its requirements. |
| */ |
| |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); |
| |
| /** @file |
| * |
| * Generic UARTs |
| * |
| */ |
| |
| #include <stdlib.h> |
| #include <strings.h> |
| #include <errno.h> |
| #include <ipxe/uart.h> |
| |
| /** List of registered UARTs */ |
| LIST_HEAD ( uarts ); |
| |
| static void null_uart_transmit ( struct uart *uart __unused, |
| uint8_t byte __unused ) { |
| } |
| |
| static int null_uart_data_ready ( struct uart *uart __unused ) { |
| return 0; |
| } |
| |
| static uint8_t null_uart_receive ( struct uart *uart __unused ) { |
| return 0; |
| } |
| |
| static int null_uart_init ( struct uart *uart __unused ) { |
| return 0; |
| } |
| |
| static void null_uart_flush ( struct uart *uart __unused ) { |
| } |
| |
| /** Null UART operations */ |
| struct uart_operations null_uart_operations = { |
| .transmit = null_uart_transmit, |
| .data_ready = null_uart_data_ready, |
| .receive = null_uart_receive, |
| .init = null_uart_init, |
| .flush = null_uart_flush, |
| }; |
| |
| /** |
| * Allocate UART |
| * |
| * @v priv_len Length of private data |
| * @ret uart UART, or NULL on error |
| */ |
| struct uart * alloc_uart ( size_t priv_len ) { |
| struct uart *uart; |
| |
| /* Allocate and initialise UART */ |
| uart = zalloc ( sizeof ( *uart ) + priv_len ); |
| if ( ! uart ) |
| return NULL; |
| uart->priv = ( ( ( void * ) uart ) + sizeof ( *uart ) ); |
| |
| return uart; |
| } |
| |
| /** |
| * Register fixed UARTs (when not provided by platform) |
| * |
| * @ret rc Return status code |
| */ |
| __weak int uart_register_fixed ( void ) { |
| |
| return 0; |
| } |
| |
| /** |
| * Register UART |
| * |
| * @v uart UART |
| * @ret rc Return status code |
| */ |
| int uart_register ( struct uart *uart ) { |
| |
| /* Add to list of registered UARTs */ |
| uart_get ( uart ); |
| list_add_tail ( &uart->list, &uarts ); |
| DBGC ( uart, "UART %s registered\n", uart->name ); |
| |
| return 0; |
| } |
| |
| /** |
| * Unregister UART |
| * |
| * @v uart UART |
| */ |
| void uart_unregister ( struct uart *uart ) { |
| |
| /* Remove from list of registered UARTs */ |
| list_del ( &uart->list ); |
| uart_put ( uart ); |
| } |
| |
| /** |
| * Find named UART |
| * |
| * @v name UART name |
| * @ret uart UART, or NULL if not found |
| */ |
| struct uart * uart_find ( const char *name ) { |
| struct uart *uart; |
| unsigned int index; |
| char *endp; |
| int rc; |
| |
| /* Register fixed platform UARTs if not already registered */ |
| if ( list_empty ( &uarts ) ) { |
| if ( ( rc = uart_register_fixed() ) != 0 ) { |
| DBGC ( &uarts, "UART could not register fixed UARTs: " |
| "%s\n", strerror ( rc ) ); |
| /* Continue anyway */ |
| } |
| } |
| |
| /* Try parsing name as a numeric index */ |
| index = strtoul ( name, &endp, 10 ); |
| |
| /* Find matching UART, if any */ |
| list_for_each_entry ( uart, &uarts, list ) { |
| |
| /* Check for a matching name */ |
| if ( strcasecmp ( name, uart->name ) == 0 ) |
| return uart; |
| |
| /* Check for a matching numeric index */ |
| if ( ( *endp == '\0' ) && ( index-- == 0 ) ) |
| return uart; |
| } |
| |
| DBGC ( &uarts, "UART %s not found\n", name ); |
| return NULL; |
| } |