1 /* 2 * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2012-2015, Haiku, Inc. All rights reserved. 6 * Distributed under the terms of the MIT License. 7 * 8 * Authors: 9 * Axel Dörfler, axeld@pinc-software.de 10 * Alexander von Gluck IV, kallisti5@unixzen.com 11 */ 12 13 14 #include "serial.h" 15 16 #include <arch/generic/debug_uart_8250.h> 17 18 #if defined(__ARM__) 19 #include <arch/arm/arch_uart_pl011.h> 20 #endif 21 22 #include <board_config.h> 23 #include <boot/platform.h> 24 #include <arch/cpu.h> 25 #include <boot/stage2.h> 26 #include <new> 27 #include <string.h> 28 29 extern "C" { 30 #include <fdt.h> 31 #include <libfdt.h> 32 #include <libfdt_env.h> 33 }; 34 35 #include "fdt_serial.h" 36 37 38 DebugUART* gUART; 39 40 static int32 sSerialEnabled = 0; 41 static char sBuffer[16384]; 42 static uint32 sBufferPosition; 43 44 45 static void 46 serial_putc(char c) 47 { 48 if (gUART == NULL || sSerialEnabled <= 0) 49 return; 50 51 gUART->PutChar(c); 52 } 53 54 55 extern "C" int 56 serial_getc(bool wait) 57 { 58 if (gUART == NULL || sSerialEnabled <= 0) 59 return 0; 60 61 return gUART->GetChar(wait); 62 } 63 64 65 extern "C" void 66 serial_puts(const char* string, size_t size) 67 { 68 if (sSerialEnabled <= 0) 69 return; 70 71 if (sBufferPosition + size < sizeof(sBuffer)) { 72 memcpy(sBuffer + sBufferPosition, string, size); 73 sBufferPosition += size; 74 } 75 76 while (size-- != 0) { 77 char c = string[0]; 78 79 if (c == '\n') { 80 serial_putc('\r'); 81 serial_putc('\n'); 82 } else if (c != '\r') 83 serial_putc(c); 84 85 string++; 86 } 87 } 88 89 90 extern "C" void 91 serial_disable(void) 92 { 93 sSerialEnabled = 0; 94 } 95 96 97 extern "C" void 98 serial_enable(void) 99 { 100 /* should already be initialized by U-Boot */ 101 gUART->InitEarly(); 102 gUART->InitPort(115200); 103 sSerialEnabled++; 104 } 105 106 107 extern "C" void 108 serial_cleanup(void) 109 { 110 if (sSerialEnabled <= 0) 111 return; 112 113 gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition); 114 if (gKernelArgs.debug_output != NULL) { 115 memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition); 116 gKernelArgs.debug_size = sBufferPosition; 117 } 118 } 119 120 121 extern "C" void 122 serial_init(const void *fdt) 123 { 124 // first try with hints from the FDT 125 gUART = debug_uart_from_fdt(fdt); 126 127 // fallback to known board UARTs 128 #if defined(BOARD_UART_DEBUG) && defined(BOARD_UART_CLOCK) 129 if (gUART == NULL) { 130 #ifdef BOARD_UART_PL011 131 gUART = arch_get_uart_pl011(BOARD_UART_DEBUG, BOARD_UART_CLOCK); 132 #else 133 gUART = arch_get_uart_8250(BOARD_UART_DEBUG, BOARD_UART_CLOCK); 134 #endif 135 } 136 #endif 137 138 if (gUART == NULL) 139 return; 140 141 serial_enable(); 142 } 143