serial.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 FILE_LICENCE ( GPL2_OR_LATER );
00015
00016 #include "stddef.h"
00017 #include <gpxe/init.h>
00018 #include <gpxe/io.h>
00019 #include <unistd.h>
00020 #include <gpxe/serial.h>
00021 #include "config/serial.h"
00022
00023
00024
00025 #ifndef COMCONSOLE
00026 #define COMCONSOLE 0x3f8
00027 #endif
00028
00029 #ifndef COMSPEED
00030 #define COMSPEED 9600
00031 #endif
00032
00033 #ifndef COMDATA
00034 #define COMDATA 8
00035 #endif
00036
00037 #ifndef COMPARITY
00038 #define COMPARITY 0
00039 #endif
00040
00041 #ifndef COMSTOP
00042 #define COMSTOP 1
00043 #endif
00044
00045 #undef UART_BASE
00046 #define UART_BASE ( COMCONSOLE )
00047
00048 #undef UART_BAUD
00049 #define UART_BAUD ( COMSPEED )
00050
00051 #if ((115200%UART_BAUD) != 0)
00052 #error Bad ttys0 baud rate
00053 #endif
00054
00055 #define COMBRD (115200/UART_BAUD)
00056
00057
00058 #define UART_LCS ( ( ( (COMDATA) - 5 ) << 0 ) | \
00059 ( ( (COMPARITY) ) << 3 ) | \
00060 ( ( (COMSTOP) - 1 ) << 2 ) )
00061
00062
00063 #define UART_RBR 0x00
00064 #define UART_TBR 0x00
00065
00066
00067 #define UART_IER 0x01
00068 #define UART_IIR 0x02
00069 #define UART_FCR 0x02
00070 #define UART_LCR 0x03
00071 #define UART_MCR 0x04
00072 #define UART_DLL 0x00
00073 #define UART_DLM 0x01
00074
00075
00076 #define UART_LSR 0x05
00077 #define UART_LSR_TEMPT 0x40
00078 #define UART_LSR_THRE 0x20
00079 #define UART_LSR_BI 0x10
00080 #define UART_LSR_FE 0x08
00081 #define UART_LSR_PE 0x04
00082 #define UART_LSR_OE 0x02
00083 #define UART_LSR_DR 0x01
00084
00085 #define UART_MSR 0x06
00086 #define UART_SCR 0x07
00087
00088 #if defined(UART_MEM)
00089 #define uart_readb(addr) readb((addr))
00090 #define uart_writeb(val,addr) writeb((val),(addr))
00091 #else
00092 #define uart_readb(addr) inb((addr))
00093 #define uart_writeb(val,addr) outb((val),(addr))
00094 #endif
00095
00096
00097
00098
00099
00100 void serial_putc ( int ch ) {
00101 int i;
00102 int status;
00103 i = 1000;
00104 while(--i > 0) {
00105 status = uart_readb(UART_BASE + UART_LSR);
00106 if (status & UART_LSR_THRE) {
00107
00108 uart_writeb(ch, UART_BASE + UART_TBR);
00109 break;
00110 }
00111 mdelay(2);
00112 }
00113 }
00114
00115
00116
00117
00118
00119 int serial_getc ( void ) {
00120 int status;
00121 int ch;
00122 do {
00123 status = uart_readb(UART_BASE + UART_LSR);
00124 } while((status & 1) == 0);
00125 ch = uart_readb(UART_BASE + UART_RBR);
00126 ch &= 0x7f;
00127 if (ch == 0x7f) {
00128 ch = 0x08;
00129 }
00130 return ch;
00131 }
00132
00133
00134
00135
00136
00137
00138 int serial_ischar ( void ) {
00139 int status;
00140 status = uart_readb(UART_BASE + UART_LSR);
00141 return status & 1;
00142 }
00143
00144
00145
00146
00147
00148 static void serial_init ( void ) {
00149 int status;
00150 int divisor, lcs;
00151
00152 DBG ( "Serial port %#x initialising\n", UART_BASE );
00153
00154 divisor = COMBRD;
00155 lcs = UART_LCS;
00156
00157
00158 #ifdef COMPRESERVE
00159 lcs = uart_readb(UART_BASE + UART_LCR) & 0x7f;
00160 uart_writeb(0x80 | lcs, UART_BASE + UART_LCR);
00161 divisor = (uart_readb(UART_BASE + UART_DLM) << 8) | uart_readb(UART_BASE + UART_DLL);
00162 uart_writeb(lcs, UART_BASE + UART_LCR);
00163 #endif
00164
00165
00166
00167
00168 uart_writeb(0x80 | lcs, UART_BASE + UART_LCR);
00169 uart_writeb(0xaa, UART_BASE + UART_DLL);
00170 if (uart_readb(UART_BASE + UART_DLL) != 0xaa) {
00171 DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE );
00172 goto out;
00173 }
00174 uart_writeb(0x55, UART_BASE + UART_DLL);
00175 if (uart_readb(UART_BASE + UART_DLL) != 0x55) {
00176 DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE );
00177 goto out;
00178 }
00179 uart_writeb(divisor & 0xff, UART_BASE + UART_DLL);
00180 if (uart_readb(UART_BASE + UART_DLL) != (divisor & 0xff)) {
00181 DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE );
00182 goto out;
00183 }
00184 uart_writeb(0xaa, UART_BASE + UART_DLM);
00185 if (uart_readb(UART_BASE + UART_DLM) != 0xaa) {
00186 DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE );
00187 goto out;
00188 }
00189 uart_writeb(0x55, UART_BASE + UART_DLM);
00190 if (uart_readb(UART_BASE + UART_DLM) != 0x55) {
00191 DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE );
00192 goto out;
00193 }
00194 uart_writeb((divisor >> 8) & 0xff, UART_BASE + UART_DLM);
00195 if (uart_readb(UART_BASE + UART_DLM) != ((divisor >> 8) & 0xff)) {
00196 DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE );
00197 goto out;
00198 }
00199 uart_writeb(lcs, UART_BASE + UART_LCR);
00200
00201
00202 uart_writeb(0x0, UART_BASE + UART_IER);
00203
00204
00205 uart_writeb(0x00, UART_BASE + UART_FCR);
00206
00207
00208 uart_writeb((1<<1), UART_BASE + UART_MCR);
00209
00210
00211
00212 do {
00213
00214
00215
00216 (void) uart_readb(UART_BASE + UART_RBR);
00217
00218 status = uart_readb(UART_BASE + UART_LSR);
00219 } while(status & UART_LSR_DR);
00220 out:
00221 return;
00222 }
00223
00224
00225
00226
00227
00228
00229 static void serial_fini ( int flags __unused ) {
00230 int i, status;
00231
00232
00233
00234 i = 10000;
00235 do {
00236 status = uart_readb(UART_BASE + UART_LSR);
00237 } while((--i > 0) && !(status & UART_LSR_TEMPT));
00238
00239 }
00240
00241
00242
00243
00244
00245
00246
00247 struct init_fn serial_init_fn __init_fn ( INIT_SERIAL ) = {
00248 .initialise = serial_init,
00249 };
00250
00251
00252 struct startup_fn serial_startup_fn __startup_fn ( STARTUP_EARLY ) = {
00253 .shutdown = serial_fini,
00254 };