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 <boot/platform.h> 23 #include <arch/cpu.h> 24 #include <boot/stage2.h> 25 #include <new> 26 #include <string.h> 27 28 extern "C" { 29 #include <fdt.h> 30 #include <libfdt.h> 31 #include <libfdt_env.h> 32 }; 33 34 #include "fdt_serial.h" 35 36 37 DebugUART* gUART; 38 39 static int32 sSerialEnabled = 0; 40 static char sBuffer[16384]; 41 static uint32 sBufferPosition; 42 43 44 static void 45 serial_putc(char c) 46 { 47 if (gUART == NULL || sSerialEnabled <= 0) 48 return; 49 50 gUART->PutChar(c); 51 } 52 53 54 extern "C" int 55 serial_getc(bool wait) 56 { 57 if (gUART == NULL || sSerialEnabled <= 0) 58 return 0; 59 60 return gUART->GetChar(wait); 61 } 62 63 64 extern "C" void 65 serial_puts(const char* string, size_t size) 66 { 67 if (sSerialEnabled <= 0) 68 return; 69 70 if (sBufferPosition + size < sizeof(sBuffer)) { 71 memcpy(sBuffer + sBufferPosition, string, size); 72 sBufferPosition += size; 73 } 74 75 while (size-- != 0) { 76 char c = string[0]; 77 78 if (c == '\n') { 79 serial_putc('\r'); 80 serial_putc('\n'); 81 } else if (c != '\r') 82 serial_putc(c); 83 84 string++; 85 } 86 } 87 88 89 extern "C" void 90 serial_disable(void) 91 { 92 sSerialEnabled = 0; 93 } 94 95 96 extern "C" void 97 serial_enable(void) 98 { 99 /* should already be initialized by U-Boot */ 100 gUART->InitEarly(); 101 gUART->InitPort(115200); 102 sSerialEnabled++; 103 } 104 105 106 extern "C" void 107 serial_cleanup(void) 108 { 109 if (sSerialEnabled <= 0) 110 return; 111 112 gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition); 113 if (gKernelArgs.debug_output != NULL) { 114 memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition); 115 gKernelArgs.debug_size = sBufferPosition; 116 } 117 } 118 119 120 extern "C" void 121 serial_init(const void *fdt) 122 { 123 // first try with hints from the FDT 124 gUART = debug_uart_from_fdt(fdt); 125 126 // Do we can some kind of direct fallback here 127 // (aka, guess arch_get_uart_pl011 or arch_get_uart_8250?) 128 if (gUART == NULL) 129 return; 130 131 serial_enable(); 132 } 133