xref: /haiku/src/system/boot/platform/u-boot/serial.cpp (revision 81ec973846ea4816c53ed8901822e43c8b06878d)
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, Alexander von Gluck, kallisti5@unixzen.com
6  * Distributed under the terms of the MIT License.
7  */
8 
9 
10 #include "serial.h"
11 
12 #include <debug_uart_8250.h>
13 #include <board_config.h>
14 #include <boot/platform.h>
15 #include <arch/cpu.h>
16 #include <boot/stage2.h>
17 #include <new>
18 #include <string.h>
19 
20 extern "C" {
21 #include <fdt.h>
22 #include <libfdt.h>
23 #include <libfdt_env.h>
24 };
25 
26 
27 extern "C" DebugUART *debug_uart_from_fdt(const void *fdt);
28 
29 DebugUART* gUART;
30 
31 static int32 sSerialEnabled = 0;
32 static char sBuffer[16384];
33 static uint32 sBufferPosition;
34 
35 
36 static void
37 serial_putc(char c)
38 {
39 	gUART->PutChar(c);
40 }
41 
42 
43 extern "C" int
44 serial_getc(bool wait)
45 {
46 	return gUART->GetChar(wait);
47 }
48 
49 
50 extern "C" void
51 serial_puts(const char* string, size_t size)
52 {
53 	if (sSerialEnabled <= 0)
54 		return;
55 
56 	if (sBufferPosition + size < sizeof(sBuffer)) {
57 		memcpy(sBuffer + sBufferPosition, string, size);
58 		sBufferPosition += size;
59 	}
60 
61 	while (size-- != 0) {
62 		char c = string[0];
63 
64 		if (c == '\n') {
65 			serial_putc('\r');
66 			serial_putc('\n');
67 		} else if (c != '\r')
68 			serial_putc(c);
69 
70 		string++;
71 	}
72 }
73 
74 
75 extern "C" void
76 serial_disable(void)
77 {
78 	sSerialEnabled = 0;
79 }
80 
81 
82 extern "C" void
83 serial_enable(void)
84 {
85 	/* should already be initialized by U-Boot */
86 	/*
87 	gUART->InitEarly();
88 	gUART->InitPort(9600);
89 	*/
90 	sSerialEnabled++;
91 }
92 
93 
94 extern "C" void
95 serial_cleanup(void)
96 {
97 	if (sSerialEnabled <= 0)
98 		return;
99 
100 	gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition);
101 	if (gKernelArgs.debug_output != NULL) {
102 		memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition);
103 		gKernelArgs.debug_size = sBufferPosition;
104 	}
105 }
106 
107 
108 extern "C" void
109 serial_init(const void *fdt)
110 {
111 	// first try with hints from the FDT
112 	gUART = debug_uart_from_fdt(fdt);
113 
114 #ifdef BOARD_UART_DEBUG
115 	// fallback to hardcoded board UART
116 	if (gUART == NULL)
117 		gUART = arch_get_uart_8250(BOARD_UART_DEBUG, BOARD_UART_CLOCK);
118 #endif
119 
120 	if (gUART == NULL)
121 		return;
122 
123 	serial_enable();
124 }
125