xref: /haiku/src/system/kernel/arch/generic/debug_uart_8250.cpp (revision 3d4afef9cba2f328e238089d4609d00d4b1524f3)
1 /*
2  * Copyright (c) 2008 Travis Geiselbrecht
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 
25 #include <arch/generic/debug_uart_8250.h>
26 #include <debug.h>
27 #include <new>
28 
29 
30 DebugUART8250::DebugUART8250(addr_t base, int64 clock)
31 	:
32 	DebugUART(base, clock)
33 {
34 }
35 
36 
37 DebugUART8250::~DebugUART8250()
38 {
39 }
40 
41 
42 #define UART_RHR    0
43 #define UART_THR    0
44 #define UART_DLL    0
45 #define UART_IER    1
46 #define UART_DLH    1
47 #define UART_IIR    2
48 #define UART_FCR    2
49 #define UART_EFR    2
50 #define UART_LCR    3
51 #define UART_MCR    4
52 #define UART_LSR    5
53 #define UART_MSR    6
54 #define UART_TCR    6
55 #define UART_SPR    7
56 #define UART_TLR    7
57 
58 #define LCR_8N1		0x03
59 
60 #define FCR_FIFO_EN	0x01	/* Fifo enable */
61 #define FCR_RXSR	0x02	/* Receiver soft reset */
62 #define FCR_TXSR	0x04	/* Transmitter soft reset */
63 
64 #define MCR_DTR		0x01
65 #define MCR_RTS		0x02
66 #define MCR_DMA_EN	0x04
67 #define MCR_TX_DFR	0x08
68 
69 #define LCR_WLS_MSK	0x03	/* character length select mask */
70 #define LCR_WLS_5	0x00	/* 5 bit character length */
71 #define LCR_WLS_6	0x01	/* 6 bit character length */
72 #define LCR_WLS_7	0x02	/* 7 bit character length */
73 #define LCR_WLS_8	0x03	/* 8 bit character length */
74 #define LCR_STB		0x04	/* Number of stop Bits, off = 1, on = 1.5 or 2) */
75 #define LCR_PEN		0x08	/* Parity eneble */
76 #define LCR_EPS		0x10	/* Even Parity Select */
77 #define LCR_STKP	0x20	/* Stick Parity */
78 #define LCR_SBRK	0x40	/* Set Break */
79 #define LCR_BKSE	0x80	/* Bank select enable */
80 
81 #define LSR_DR		0x01	/* Data ready */
82 #define LSR_OE		0x02	/* Overrun */
83 #define LSR_PE		0x04	/* Parity error */
84 #define LSR_FE		0x08	/* Framing error */
85 #define LSR_BI		0x10	/* Break */
86 #define LSR_THRE	0x20	/* Xmit holding register empty */
87 #define LSR_TEMT	0x40	/* Xmitter empty */
88 #define LSR_ERR		0x80	/* Error */
89 
90 
91 void
92 DebugUART8250::InitPort(uint32 baud)
93 {
94 	Disable();
95 
96 	uint16 baudDivisor = Clock() / (16 * baud);
97 
98 	// Write standard uart settings
99 	Out8(UART_LCR, LCR_8N1);
100 	// 8N1
101 	Out8(UART_IER, 0);
102 	// Disable interrupt
103 	Out8(UART_FCR, 0);
104 	// Disable FIFO
105 	Out8(UART_MCR, MCR_DTR | MCR_RTS);
106 	// DTR / RTS
107 
108 	// Gain access to, and program baud divisor
109 	unsigned char buffer = In8(UART_LCR);
110 	Out8(UART_LCR, buffer | LCR_BKSE);
111 	Out8(UART_DLL, baudDivisor & 0xff);
112 	Out8(UART_DLH, (baudDivisor >> 8) & 0xff);
113 	Out8(UART_LCR, buffer & ~LCR_BKSE);
114 
115 //	Out8(UART_MDR1, 0); // UART 16x mode
116 //	Out8(UART_LCR, 0xBF); // config mode B
117 //	Out8(UART_EFR, (1<<7)|(1<<6)); // hw flow control
118 //	Out8(UART_LCR, LCR_8N1); // operational mode
119 
120 	Enable();
121 }
122 
123 
124 void
125 DebugUART8250::InitEarly()
126 {
127 }
128 
129 
130 void
131 DebugUART8250::Init()
132 {
133 }
134 
135 
136 int
137 DebugUART8250::PutChar(char c)
138 {
139 	while (!(In8(UART_LSR) & (1<<6)));
140 		// wait for the last char to get out
141 	Out8(UART_THR, c);
142 	return 0;
143 }
144 
145 
146 /* returns -1 if no data available */
147 int
148 DebugUART8250::GetChar(bool wait)
149 {
150 	if (wait) {
151 		while (!(In8(UART_LSR) & (1<<0)));
152 			// wait for data to show up in the rx fifo
153 	} else {
154 		if (!(In8(UART_LSR) & (1<<0)))
155 			return -1;
156 	}
157 	return In8(UART_RHR);
158 }
159 
160 
161 void
162 DebugUART8250::FlushTx()
163 {
164 	while (!(In8(UART_LSR) & (1<<6)));
165 		// wait for the last char to get out
166 }
167 
168 
169 void
170 DebugUART8250::FlushRx()
171 {
172 	// empty the rx fifo
173 	while (In8(UART_LSR) & (1<<0)) {
174 		volatile char c = In8(UART_RHR);
175 		(void)c;
176 	}
177 }
178 
179 
180 void
181 DebugUART8250::Barrier()
182 {
183 	// Simple memory barriers
184 #if defined(__POWERPC__)
185 	asm volatile("eieio; sync");
186 #elif defined(__ARM__)
187 	asm volatile ("" : : : "memory");
188 #endif
189 }
190 
191 
192 DebugUART8250*
193 arch_get_uart_8250(addr_t base, int64 clock)
194 {
195 	static char buffer[sizeof(DebugUART8250)];
196 	DebugUART8250* uart = new(buffer) DebugUART8250(base, clock);
197 	return uart;
198 }
199 
200