|  | @@ -1,259 +1,184 @@
 | 
		
	
		
			
			| 1 | 1 |  /*
 | 
		
	
		
			
			| 2 |  | - * The serial port interface routines implement a simple polled i/o
 | 
		
	
		
			
			| 3 |  | - * interface to a standard serial port.  Due to the space restrictions
 | 
		
	
		
			
			| 4 |  | - * for the boot blocks, no BIOS support is used (since BIOS requires
 | 
		
	
		
			
			| 5 |  | - * expensive real/protected mode switches), instead the rudimentary
 | 
		
	
		
			
			| 6 |  | - * BIOS support is duplicated here.
 | 
		
	
		
			
			|  | 2 | + * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
 | 
		
	
		
			
			| 7 | 3 |   *
 | 
		
	
		
			
			| 8 |  | - * The base address and speed for the i/o port are passed from the
 | 
		
	
		
			
			| 9 |  | - * Makefile in the COMCONSOLE and CONSPEED preprocessor macros.  The
 | 
		
	
		
			
			| 10 |  | - * line control parameters are currently hard-coded to 8 bits, no
 | 
		
	
		
			
			| 11 |  | - * parity, 1 stop bit (8N1).  This can be changed in init_serial().
 | 
		
	
		
			
			|  | 4 | + * This program is free software; you can redistribute it and/or
 | 
		
	
		
			
			|  | 5 | + * modify it under the terms of the GNU General Public License as
 | 
		
	
		
			
			|  | 6 | + * published by the Free Software Foundation; either version 2 of the
 | 
		
	
		
			
			|  | 7 | + * License, or any later version.
 | 
		
	
		
			
			|  | 8 | + *
 | 
		
	
		
			
			|  | 9 | + * This program is distributed in the hope that it will be useful, but
 | 
		
	
		
			
			|  | 10 | + * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
		
	
		
			
			|  | 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
		
	
		
			
			|  | 12 | + * General Public License for more details.
 | 
		
	
		
			
			|  | 13 | + *
 | 
		
	
		
			
			|  | 14 | + * You should have received a copy of the GNU General Public License
 | 
		
	
		
			
			|  | 15 | + * along with this program; if not, write to the Free Software
 | 
		
	
		
			
			|  | 16 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
		
	
		
			
			|  | 17 | + * 02110-1301, USA.
 | 
		
	
		
			
			|  | 18 | + *
 | 
		
	
		
			
			|  | 19 | + * You can also choose to distribute this program under the terms of
 | 
		
	
		
			
			|  | 20 | + * the Unmodified Binary Distribution Licence (as given in the file
 | 
		
	
		
			
			|  | 21 | + * COPYING.UBDL), provided that you have satisfied its requirements.
 | 
		
	
		
			
			| 12 | 22 |   */
 | 
		
	
		
			
			| 13 | 23 |  
 | 
		
	
		
			
			| 14 |  | -FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			|  | 24 | +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
		
	
		
			
			|  | 25 | +
 | 
		
	
		
			
			|  | 26 | +/** @file
 | 
		
	
		
			
			|  | 27 | + *
 | 
		
	
		
			
			|  | 28 | + * Serial console
 | 
		
	
		
			
			|  | 29 | + *
 | 
		
	
		
			
			|  | 30 | + */
 | 
		
	
		
			
			| 15 | 31 |  
 | 
		
	
		
			
			| 16 |  | -#include "stddef.h"
 | 
		
	
		
			
			|  | 32 | +#include <stddef.h>
 | 
		
	
		
			
			| 17 | 33 |  #include <ipxe/init.h>
 | 
		
	
		
			
			| 18 |  | -#include <ipxe/io.h>
 | 
		
	
		
			
			| 19 |  | -#include <unistd.h>
 | 
		
	
		
			
			|  | 34 | +#include <ipxe/uart.h>
 | 
		
	
		
			
			|  | 35 | +#include <ipxe/console.h>
 | 
		
	
		
			
			| 20 | 36 |  #include <ipxe/serial.h>
 | 
		
	
		
			
			| 21 |  | -#include "config/serial.h"
 | 
		
	
		
			
			| 22 |  | -
 | 
		
	
		
			
			| 23 |  | -/* Set default values if none specified */
 | 
		
	
		
			
			|  | 37 | +#include <config/console.h>
 | 
		
	
		
			
			|  | 38 | +#include <config/serial.h>
 | 
		
	
		
			
			| 24 | 39 |  
 | 
		
	
		
			
			| 25 |  | -#ifndef COMCONSOLE
 | 
		
	
		
			
			| 26 |  | -#define COMCONSOLE	0x3f8
 | 
		
	
		
			
			|  | 40 | +/* Set default console usage if applicable */
 | 
		
	
		
			
			|  | 41 | +#if ! ( defined ( CONSOLE_SERIAL ) && CONSOLE_EXPLICIT ( CONSOLE_SERIAL ) )
 | 
		
	
		
			
			|  | 42 | +#undef CONSOLE_SERIAL
 | 
		
	
		
			
			|  | 43 | +#define CONSOLE_SERIAL ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
 | 
		
	
		
			
			| 27 | 44 |  #endif
 | 
		
	
		
			
			| 28 | 45 |  
 | 
		
	
		
			
			| 29 |  | -#ifndef COMSPEED
 | 
		
	
		
			
			| 30 |  | -#define COMSPEED	9600
 | 
		
	
		
			
			| 31 |  | -#endif
 | 
		
	
		
			
			| 32 |  | -
 | 
		
	
		
			
			| 33 |  | -#ifndef COMDATA
 | 
		
	
		
			
			| 34 |  | -#define COMDATA		8
 | 
		
	
		
			
			|  | 46 | +/* UART port number */
 | 
		
	
		
			
			|  | 47 | +#ifdef COMCONSOLE
 | 
		
	
		
			
			|  | 48 | +#define CONSOLE_PORT COMCONSOLE
 | 
		
	
		
			
			|  | 49 | +#else
 | 
		
	
		
			
			|  | 50 | +#define CONSOLE_PORT 0
 | 
		
	
		
			
			| 35 | 51 |  #endif
 | 
		
	
		
			
			| 36 | 52 |  
 | 
		
	
		
			
			| 37 |  | -#ifndef COMPARITY
 | 
		
	
		
			
			| 38 |  | -#define COMPARITY	0
 | 
		
	
		
			
			|  | 53 | +/* UART baud rate */
 | 
		
	
		
			
			|  | 54 | +#ifdef COMPRESERVE
 | 
		
	
		
			
			|  | 55 | +#define CONSOLE_BAUD 0
 | 
		
	
		
			
			|  | 56 | +#else
 | 
		
	
		
			
			|  | 57 | +#define CONSOLE_BAUD COMSPEED
 | 
		
	
		
			
			| 39 | 58 |  #endif
 | 
		
	
		
			
			| 40 | 59 |  
 | 
		
	
		
			
			| 41 |  | -#ifndef COMSTOP
 | 
		
	
		
			
			| 42 |  | -#define COMSTOP		1
 | 
		
	
		
			
			|  | 60 | +/* UART line control register value */
 | 
		
	
		
			
			|  | 61 | +#ifdef COMPRESERVE
 | 
		
	
		
			
			|  | 62 | +#define CONSOLE_LCR 0
 | 
		
	
		
			
			|  | 63 | +#else
 | 
		
	
		
			
			|  | 64 | +#define CONSOLE_LCR UART_LCR_WPS ( COMDATA, COMPARITY, COMSTOP )
 | 
		
	
		
			
			| 43 | 65 |  #endif
 | 
		
	
		
			
			| 44 | 66 |  
 | 
		
	
		
			
			| 45 |  | -#undef UART_BASE
 | 
		
	
		
			
			| 46 |  | -#define UART_BASE ( COMCONSOLE )
 | 
		
	
		
			
			| 47 |  | -
 | 
		
	
		
			
			| 48 |  | -#undef UART_BAUD
 | 
		
	
		
			
			| 49 |  | -#define UART_BAUD ( COMSPEED )
 | 
		
	
		
			
			|  | 67 | +/** Serial console UART */
 | 
		
	
		
			
			|  | 68 | +struct uart serial_console;
 | 
		
	
		
			
			| 50 | 69 |  
 | 
		
	
		
			
			| 51 |  | -#if ((115200%UART_BAUD) != 0)
 | 
		
	
		
			
			| 52 |  | -#error Bad ttys0 baud rate
 | 
		
	
		
			
			| 53 |  | -#endif
 | 
		
	
		
			
			| 54 |  | -
 | 
		
	
		
			
			| 55 |  | -#define COMBRD (115200/UART_BAUD)
 | 
		
	
		
			
			|  | 70 | +/**
 | 
		
	
		
			
			|  | 71 | + * Print a character to serial console
 | 
		
	
		
			
			|  | 72 | + *
 | 
		
	
		
			
			|  | 73 | + * @v character		Character to be printed
 | 
		
	
		
			
			|  | 74 | + */
 | 
		
	
		
			
			|  | 75 | +static void serial_putchar ( int character ) {
 | 
		
	
		
			
			| 56 | 76 |  
 | 
		
	
		
			
			| 57 |  | -/* Line Control Settings */
 | 
		
	
		
			
			| 58 |  | -#define UART_LCS ( ( ( (COMDATA) - 5 )	<< 0 ) | \
 | 
		
	
		
			
			| 59 |  | -		   ( ( (COMPARITY) )	<< 3 ) | \
 | 
		
	
		
			
			| 60 |  | -		   ( ( (COMSTOP) - 1 )	<< 2 ) )
 | 
		
	
		
			
			|  | 77 | +	/* Do nothing if we have no UART */
 | 
		
	
		
			
			|  | 78 | +	if ( ! serial_console.base )
 | 
		
	
		
			
			|  | 79 | +		return;
 | 
		
	
		
			
			| 61 | 80 |  
 | 
		
	
		
			
			| 62 |  | -/* Data */
 | 
		
	
		
			
			| 63 |  | -#define UART_RBR 0x00
 | 
		
	
		
			
			| 64 |  | -#define UART_TBR 0x00
 | 
		
	
		
			
			|  | 81 | +	/* Transmit character */
 | 
		
	
		
			
			|  | 82 | +	uart_transmit ( &serial_console, character );
 | 
		
	
		
			
			|  | 83 | +}
 | 
		
	
		
			
			| 65 | 84 |  
 | 
		
	
		
			
			| 66 |  | -/* Control */
 | 
		
	
		
			
			| 67 |  | -#define UART_IER 0x01
 | 
		
	
		
			
			| 68 |  | -#define UART_IIR 0x02
 | 
		
	
		
			
			| 69 |  | -#define UART_FCR 0x02
 | 
		
	
		
			
			| 70 |  | -#define UART_LCR 0x03
 | 
		
	
		
			
			| 71 |  | -#define UART_MCR 0x04
 | 
		
	
		
			
			| 72 |  | -#define UART_DLL 0x00
 | 
		
	
		
			
			| 73 |  | -#define UART_DLM 0x01
 | 
		
	
		
			
			|  | 85 | +/**
 | 
		
	
		
			
			|  | 86 | + * Get character from serial console
 | 
		
	
		
			
			|  | 87 | + *
 | 
		
	
		
			
			|  | 88 | + * @ret character	Character read from console
 | 
		
	
		
			
			|  | 89 | + */
 | 
		
	
		
			
			|  | 90 | +static int serial_getchar ( void ) {
 | 
		
	
		
			
			|  | 91 | +	uint8_t data;
 | 
		
	
		
			
			| 74 | 92 |  
 | 
		
	
		
			
			| 75 |  | -/* Status */
 | 
		
	
		
			
			| 76 |  | -#define UART_LSR 0x05
 | 
		
	
		
			
			| 77 |  | -#define  UART_LSR_TEMPT 0x40	/* Transmitter empty */
 | 
		
	
		
			
			| 78 |  | -#define  UART_LSR_THRE  0x20	/* Transmit-hold-register empty */
 | 
		
	
		
			
			| 79 |  | -#define  UART_LSR_BI	0x10	/* Break interrupt indicator */
 | 
		
	
		
			
			| 80 |  | -#define  UART_LSR_FE	0x08	/* Frame error indicator */
 | 
		
	
		
			
			| 81 |  | -#define  UART_LSR_PE	0x04	/* Parity error indicator */
 | 
		
	
		
			
			| 82 |  | -#define  UART_LSR_OE	0x02	/* Overrun error indicator */
 | 
		
	
		
			
			| 83 |  | -#define  UART_LSR_DR	0x01	/* Receiver data ready */
 | 
		
	
		
			
			|  | 93 | +	/* Do nothing if we have no UART */
 | 
		
	
		
			
			|  | 94 | +	if ( ! serial_console.base )
 | 
		
	
		
			
			|  | 95 | +		return 0;
 | 
		
	
		
			
			| 84 | 96 |  
 | 
		
	
		
			
			| 85 |  | -#define UART_MSR 0x06
 | 
		
	
		
			
			| 86 |  | -#define UART_SCR 0x07
 | 
		
	
		
			
			|  | 97 | +	/* Wait for data to be ready */
 | 
		
	
		
			
			|  | 98 | +	while ( ! uart_data_ready ( &serial_console ) ) {}
 | 
		
	
		
			
			| 87 | 99 |  
 | 
		
	
		
			
			| 88 |  | -#if defined(UART_MEM)
 | 
		
	
		
			
			| 89 |  | -#define uart_readb(addr) readb((addr))
 | 
		
	
		
			
			| 90 |  | -#define uart_writeb(val,addr) writeb((val),(addr))
 | 
		
	
		
			
			| 91 |  | -#else
 | 
		
	
		
			
			| 92 |  | -#define uart_readb(addr) inb((addr))
 | 
		
	
		
			
			| 93 |  | -#define uart_writeb(val,addr) outb((val),(addr))
 | 
		
	
		
			
			| 94 |  | -#endif
 | 
		
	
		
			
			|  | 100 | +	/* Receive data */
 | 
		
	
		
			
			|  | 101 | +	data = uart_receive ( &serial_console );
 | 
		
	
		
			
			| 95 | 102 |  
 | 
		
	
		
			
			| 96 |  | -/* Boolean for the state of serial driver initialization */
 | 
		
	
		
			
			| 97 |  | -int serial_initialized = 0;
 | 
		
	
		
			
			|  | 103 | +	/* Strip any high bit and convert DEL to backspace */
 | 
		
	
		
			
			|  | 104 | +	data &= 0x7f;
 | 
		
	
		
			
			|  | 105 | +	if ( data == 0x7f )
 | 
		
	
		
			
			|  | 106 | +		data = 0x08;
 | 
		
	
		
			
			| 98 | 107 |  
 | 
		
	
		
			
			| 99 |  | -/*
 | 
		
	
		
			
			| 100 |  | - * void serial_putc(int ch);
 | 
		
	
		
			
			| 101 |  | - *	Write character `ch' to port UART_BASE.
 | 
		
	
		
			
			| 102 |  | - */
 | 
		
	
		
			
			| 103 |  | -void serial_putc ( int ch ) {
 | 
		
	
		
			
			| 104 |  | -	int i;
 | 
		
	
		
			
			| 105 |  | -	int status;
 | 
		
	
		
			
			| 106 |  | -	i = 1000; /* timeout */
 | 
		
	
		
			
			| 107 |  | -	while(--i > 0) {
 | 
		
	
		
			
			| 108 |  | -		status = uart_readb(UART_BASE + UART_LSR);
 | 
		
	
		
			
			| 109 |  | -		if (status & UART_LSR_THRE) { 
 | 
		
	
		
			
			| 110 |  | -			/* TX buffer emtpy */
 | 
		
	
		
			
			| 111 |  | -			uart_writeb(ch, UART_BASE + UART_TBR);
 | 
		
	
		
			
			| 112 |  | -			break;
 | 
		
	
		
			
			| 113 |  | -		}
 | 
		
	
		
			
			| 114 |  | -		mdelay(2);
 | 
		
	
		
			
			| 115 |  | -	}
 | 
		
	
		
			
			|  | 108 | +	return data;
 | 
		
	
		
			
			| 116 | 109 |  }
 | 
		
	
		
			
			| 117 | 110 |  
 | 
		
	
		
			
			| 118 |  | -/*
 | 
		
	
		
			
			| 119 |  | - * int serial_getc(void);
 | 
		
	
		
			
			| 120 |  | - *	Read a character from port UART_BASE.
 | 
		
	
		
			
			| 121 |  | - */
 | 
		
	
		
			
			| 122 |  | -int serial_getc ( void ) {
 | 
		
	
		
			
			| 123 |  | -	int status;
 | 
		
	
		
			
			| 124 |  | -	int ch;
 | 
		
	
		
			
			| 125 |  | -	do {
 | 
		
	
		
			
			| 126 |  | -		status = uart_readb(UART_BASE + UART_LSR);
 | 
		
	
		
			
			| 127 |  | -	} while((status & 1) == 0);
 | 
		
	
		
			
			| 128 |  | -	ch = uart_readb(UART_BASE + UART_RBR);	/* fetch (first) character */
 | 
		
	
		
			
			| 129 |  | -	ch &= 0x7f;				/* remove any parity bits we get */
 | 
		
	
		
			
			| 130 |  | -	if (ch == 0x7f) {			/* Make DEL... look like BS */
 | 
		
	
		
			
			| 131 |  | -		ch = 0x08;
 | 
		
	
		
			
			| 132 |  | -	}
 | 
		
	
		
			
			| 133 |  | -	return ch;
 | 
		
	
		
			
			| 134 |  | -}
 | 
		
	
		
			
			| 135 |  | -
 | 
		
	
		
			
			| 136 |  | -/*
 | 
		
	
		
			
			| 137 |  | - * int serial_ischar(void);
 | 
		
	
		
			
			| 138 |  | - *       If there is a character in the input buffer of port UART_BASE,
 | 
		
	
		
			
			| 139 |  | - *       return nonzero; otherwise return 0.
 | 
		
	
		
			
			|  | 111 | +/**
 | 
		
	
		
			
			|  | 112 | + * Check for character ready to read from serial console
 | 
		
	
		
			
			|  | 113 | + *
 | 
		
	
		
			
			|  | 114 | + * @ret True		Character available to read
 | 
		
	
		
			
			|  | 115 | + * @ret False		No character available to read
 | 
		
	
		
			
			| 140 | 116 |   */
 | 
		
	
		
			
			| 141 |  | -int serial_ischar ( void ) {
 | 
		
	
		
			
			| 142 |  | -	int status;
 | 
		
	
		
			
			| 143 |  | -	status = uart_readb(UART_BASE + UART_LSR);	/* line status reg; */
 | 
		
	
		
			
			| 144 |  | -	return status & 1;		/* rx char available */
 | 
		
	
		
			
			| 145 |  | -}
 | 
		
	
		
			
			|  | 117 | +static int serial_iskey ( void ) {
 | 
		
	
		
			
			| 146 | 118 |  
 | 
		
	
		
			
			| 147 |  | -/*
 | 
		
	
		
			
			| 148 |  | - * int serial_init(void);
 | 
		
	
		
			
			| 149 |  | - *	Initialize port UART_BASE to speed COMSPEED, line settings 8N1.
 | 
		
	
		
			
			| 150 |  | - */
 | 
		
	
		
			
			| 151 |  | -static void serial_init ( void ) {
 | 
		
	
		
			
			| 152 |  | -	int status;
 | 
		
	
		
			
			| 153 |  | -	int divisor, lcs;
 | 
		
	
		
			
			|  | 119 | +	/* Do nothing if we have no UART */
 | 
		
	
		
			
			|  | 120 | +	if ( ! serial_console.base )
 | 
		
	
		
			
			|  | 121 | +		return 0;
 | 
		
	
		
			
			| 154 | 122 |  
 | 
		
	
		
			
			| 155 |  | -	DBG ( "Serial port %#x initialising\n", UART_BASE );
 | 
		
	
		
			
			|  | 123 | +	/* Check UART */
 | 
		
	
		
			
			|  | 124 | +	return uart_data_ready ( &serial_console );
 | 
		
	
		
			
			|  | 125 | +}
 | 
		
	
		
			
			| 156 | 126 |  
 | 
		
	
		
			
			| 157 |  | -	divisor = COMBRD;
 | 
		
	
		
			
			| 158 |  | -	lcs = UART_LCS;
 | 
		
	
		
			
			|  | 127 | +/** Serial console */
 | 
		
	
		
			
			|  | 128 | +struct console_driver serial_console_driver __console_driver = {
 | 
		
	
		
			
			|  | 129 | +	.putchar = serial_putchar,
 | 
		
	
		
			
			|  | 130 | +	.getchar = serial_getchar,
 | 
		
	
		
			
			|  | 131 | +	.iskey = serial_iskey,
 | 
		
	
		
			
			|  | 132 | +	.usage = CONSOLE_SERIAL,
 | 
		
	
		
			
			|  | 133 | +};
 | 
		
	
		
			
			| 159 | 134 |  
 | 
		
	
		
			
			|  | 135 | +/** Initialise serial console */
 | 
		
	
		
			
			|  | 136 | +static void serial_init ( void ) {
 | 
		
	
		
			
			|  | 137 | +	int rc;
 | 
		
	
		
			
			| 160 | 138 |  
 | 
		
	
		
			
			| 161 |  | -#ifdef COMPRESERVE
 | 
		
	
		
			
			| 162 |  | -	lcs = uart_readb(UART_BASE + UART_LCR) & 0x7f;
 | 
		
	
		
			
			| 163 |  | -	uart_writeb(0x80 | lcs, UART_BASE + UART_LCR);
 | 
		
	
		
			
			| 164 |  | -	divisor = (uart_readb(UART_BASE + UART_DLM) << 8) | uart_readb(UART_BASE + UART_DLL);
 | 
		
	
		
			
			| 165 |  | -	uart_writeb(lcs, UART_BASE + UART_LCR);
 | 
		
	
		
			
			| 166 |  | -#endif
 | 
		
	
		
			
			|  | 139 | +	/* Do nothing if we have no default port */
 | 
		
	
		
			
			|  | 140 | +	if ( ! CONSOLE_PORT )
 | 
		
	
		
			
			|  | 141 | +		return;
 | 
		
	
		
			
			| 167 | 142 |  
 | 
		
	
		
			
			| 168 |  | -	/* Set Baud Rate Divisor to COMSPEED, and test to see if the
 | 
		
	
		
			
			| 169 |  | -	 * serial port appears to be present.
 | 
		
	
		
			
			| 170 |  | -	 */
 | 
		
	
		
			
			| 171 |  | -	uart_writeb(0x80 | lcs, UART_BASE + UART_LCR);
 | 
		
	
		
			
			| 172 |  | -	uart_writeb(0xaa, UART_BASE + UART_DLL);
 | 
		
	
		
			
			| 173 |  | -	if (uart_readb(UART_BASE + UART_DLL) != 0xaa) {
 | 
		
	
		
			
			| 174 |  | -		DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE );
 | 
		
	
		
			
			| 175 |  | -		goto out;
 | 
		
	
		
			
			| 176 |  | -	}
 | 
		
	
		
			
			| 177 |  | -	uart_writeb(0x55, UART_BASE + UART_DLL);
 | 
		
	
		
			
			| 178 |  | -	if (uart_readb(UART_BASE + UART_DLL) != 0x55) {
 | 
		
	
		
			
			| 179 |  | -		DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE );
 | 
		
	
		
			
			| 180 |  | -		goto out;
 | 
		
	
		
			
			|  | 143 | +	/* Select UART */
 | 
		
	
		
			
			|  | 144 | +	if ( ( rc = uart_select ( &serial_console, CONSOLE_PORT ) ) != 0 ) {
 | 
		
	
		
			
			|  | 145 | +		DBG ( "Could not select UART %d: %s\n",
 | 
		
	
		
			
			|  | 146 | +		      CONSOLE_PORT, strerror ( rc ) );
 | 
		
	
		
			
			|  | 147 | +		return;
 | 
		
	
		
			
			| 181 | 148 |  	}
 | 
		
	
		
			
			| 182 |  | -	uart_writeb(divisor & 0xff, UART_BASE + UART_DLL);
 | 
		
	
		
			
			| 183 |  | -	if (uart_readb(UART_BASE + UART_DLL) != (divisor & 0xff)) {
 | 
		
	
		
			
			| 184 |  | -		DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE );
 | 
		
	
		
			
			| 185 |  | -		goto out;
 | 
		
	
		
			
			| 186 |  | -	}
 | 
		
	
		
			
			| 187 |  | -	uart_writeb(0xaa, UART_BASE + UART_DLM);
 | 
		
	
		
			
			| 188 |  | -	if (uart_readb(UART_BASE + UART_DLM) != 0xaa) {
 | 
		
	
		
			
			| 189 |  | -		DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE );
 | 
		
	
		
			
			| 190 |  | -		goto out;
 | 
		
	
		
			
			| 191 |  | -	}
 | 
		
	
		
			
			| 192 |  | -	uart_writeb(0x55, UART_BASE + UART_DLM);
 | 
		
	
		
			
			| 193 |  | -	if (uart_readb(UART_BASE + UART_DLM) != 0x55) {
 | 
		
	
		
			
			| 194 |  | -		DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE );
 | 
		
	
		
			
			| 195 |  | -		goto out;
 | 
		
	
		
			
			| 196 |  | -	}
 | 
		
	
		
			
			| 197 |  | -	uart_writeb((divisor >> 8) & 0xff, UART_BASE + UART_DLM);
 | 
		
	
		
			
			| 198 |  | -	if (uart_readb(UART_BASE + UART_DLM) != ((divisor >> 8) & 0xff)) {
 | 
		
	
		
			
			| 199 |  | -		DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE );
 | 
		
	
		
			
			| 200 |  | -		goto out;
 | 
		
	
		
			
			| 201 |  | -	}
 | 
		
	
		
			
			| 202 |  | -	uart_writeb(lcs, UART_BASE + UART_LCR);
 | 
		
	
		
			
			| 203 |  | -	
 | 
		
	
		
			
			| 204 |  | -	/* disable interrupts */
 | 
		
	
		
			
			| 205 |  | -	uart_writeb(0x0, UART_BASE + UART_IER);
 | 
		
	
		
			
			| 206 | 149 |  
 | 
		
	
		
			
			| 207 |  | -	/* enable fifos */
 | 
		
	
		
			
			| 208 |  | -	uart_writeb(0x01, UART_BASE + UART_FCR);
 | 
		
	
		
			
			|  | 150 | +	/* Initialise UART */
 | 
		
	
		
			
			|  | 151 | +	if ( ( rc = uart_init ( &serial_console, CONSOLE_BAUD,
 | 
		
	
		
			
			|  | 152 | +				CONSOLE_LCR ) ) != 0 ) {
 | 
		
	
		
			
			|  | 153 | +		DBG ( "Could not initialise UART %d baud %d LCR %#02x: %s\n",
 | 
		
	
		
			
			|  | 154 | +		      CONSOLE_PORT, CONSOLE_BAUD, CONSOLE_LCR, strerror ( rc ));
 | 
		
	
		
			
			|  | 155 | +		return;
 | 
		
	
		
			
			|  | 156 | +	}
 | 
		
	
		
			
			|  | 157 | +}
 | 
		
	
		
			
			| 209 | 158 |  
 | 
		
	
		
			
			| 210 |  | -	/* Set clear to send, so flow control works... */
 | 
		
	
		
			
			| 211 |  | -	uart_writeb((1<<1), UART_BASE + UART_MCR);
 | 
		
	
		
			
			|  | 159 | +/**
 | 
		
	
		
			
			|  | 160 | + * Shut down serial console
 | 
		
	
		
			
			|  | 161 | + *
 | 
		
	
		
			
			|  | 162 | + * @v flags		Shutdown flags
 | 
		
	
		
			
			|  | 163 | + */
 | 
		
	
		
			
			|  | 164 | +static void serial_shutdown ( int flags __unused ) {
 | 
		
	
		
			
			| 212 | 165 |  
 | 
		
	
		
			
			| 213 |  | -	/* Flush the input buffer. */
 | 
		
	
		
			
			| 214 |  | -	do {
 | 
		
	
		
			
			| 215 |  | -		/* rx buffer reg
 | 
		
	
		
			
			| 216 |  | -		 * throw away (unconditionally the first time)
 | 
		
	
		
			
			| 217 |  | -		 */
 | 
		
	
		
			
			| 218 |  | -	        (void) uart_readb(UART_BASE + UART_RBR);
 | 
		
	
		
			
			| 219 |  | -		/* line status reg */
 | 
		
	
		
			
			| 220 |  | -		status = uart_readb(UART_BASE + UART_LSR);
 | 
		
	
		
			
			| 221 |  | -	} while(status & UART_LSR_DR);
 | 
		
	
		
			
			|  | 166 | +	/* Do nothing if we have no UART */
 | 
		
	
		
			
			|  | 167 | +	if ( ! serial_console.base )
 | 
		
	
		
			
			|  | 168 | +		return;
 | 
		
	
		
			
			| 222 | 169 |  
 | 
		
	
		
			
			| 223 |  | -	/* Note that serial support has been initialized */
 | 
		
	
		
			
			| 224 |  | -	serial_initialized = 1;
 | 
		
	
		
			
			| 225 |  | - out:
 | 
		
	
		
			
			| 226 |  | -	return;
 | 
		
	
		
			
			| 227 |  | -}
 | 
		
	
		
			
			|  | 170 | +	/* Flush any pending output */
 | 
		
	
		
			
			|  | 171 | +	uart_flush ( &serial_console );
 | 
		
	
		
			
			| 228 | 172 |  
 | 
		
	
		
			
			| 229 |  | -/*
 | 
		
	
		
			
			| 230 |  | - * void serial_fini(void);
 | 
		
	
		
			
			| 231 |  | - *	Cleanup our use of the serial port, in particular flush the
 | 
		
	
		
			
			| 232 |  | - *	output buffer so we don't accidentially lose characters.
 | 
		
	
		
			
			| 233 |  | - */
 | 
		
	
		
			
			| 234 |  | -static void serial_fini ( int flags __unused ) {
 | 
		
	
		
			
			| 235 |  | -	int i, status;
 | 
		
	
		
			
			| 236 |  | -	/* Flush the output buffer to avoid dropping characters,
 | 
		
	
		
			
			| 237 |  | -	 * if we are reinitializing the serial port.
 | 
		
	
		
			
			| 238 |  | -	 */
 | 
		
	
		
			
			| 239 |  | -	i = 10000; /* timeout */
 | 
		
	
		
			
			| 240 |  | -	do {
 | 
		
	
		
			
			| 241 |  | -		status = uart_readb(UART_BASE + UART_LSR);
 | 
		
	
		
			
			| 242 |  | -	} while((--i > 0) && !(status & UART_LSR_TEMPT));
 | 
		
	
		
			
			| 243 |  | -	/* Don't mark it as disabled; it's still usable */
 | 
		
	
		
			
			|  | 173 | +	/* Leave console enabled; it's still usable */
 | 
		
	
		
			
			| 244 | 174 |  }
 | 
		
	
		
			
			| 245 | 175 |  
 | 
		
	
		
			
			| 246 |  | -/**
 | 
		
	
		
			
			| 247 |  | - * Serial driver initialisation function
 | 
		
	
		
			
			| 248 |  | - *
 | 
		
	
		
			
			| 249 |  | - * Initialise serial port early on so that it is available to capture
 | 
		
	
		
			
			| 250 |  | - * early debug messages.
 | 
		
	
		
			
			| 251 |  | - */
 | 
		
	
		
			
			| 252 |  | -struct init_fn serial_init_fn __init_fn ( INIT_SERIAL ) = {
 | 
		
	
		
			
			|  | 176 | +/** Serial console initialisation function */
 | 
		
	
		
			
			|  | 177 | +struct init_fn serial_console_init_fn __init_fn ( INIT_CONSOLE ) = {
 | 
		
	
		
			
			| 253 | 178 |  	.initialise = serial_init,
 | 
		
	
		
			
			| 254 | 179 |  };
 | 
		
	
		
			
			| 255 | 180 |  
 | 
		
	
		
			
			| 256 |  | -/** Serial driver startup function */
 | 
		
	
		
			
			|  | 181 | +/** Serial console startup function */
 | 
		
	
		
			
			| 257 | 182 |  struct startup_fn serial_startup_fn __startup_fn ( STARTUP_EARLY ) = {
 | 
		
	
		
			
			| 258 |  | -	.shutdown = serial_fini,
 | 
		
	
		
			
			|  | 183 | +	.shutdown = serial_shutdown,
 | 
		
	
		
			
			| 259 | 184 |  };
 |